Java - Append to files in loop or print entire String - java

The following Code describes my problem:
private void transact(TreeSet<BankmanagerTransaction> set) {
BankmanagerTransaction transaction;
while(!set.isEmpty()) {
transaction = set.first();
execute(transaction);
printBalance(transaction);
printLedger(transaction);
printJustifiedLedger(transaction);
}
}
Every print function prints to a different File. So I'm wondering what's best practice here.
Is it better to build string and then at the end of the transact method print everything at once, or write to the file line by line?
To make more clear what I'm trying to get at, is the time the file is being edited and therfore used by the program. Because as far as I'm aware I'd have to create a Writer for each file in the transact method and pass it to each of the 3 methods everytime.

In the most cases it's the same, but...
Your answer should change with different critereria, i.e. max String length is limited by ram, so in very very lenght cases it is better to write line by line.
But everytime you write (and flush), you are accessing the disk. In remote file locations, if the connection is very unreliable or you have latency, you can build an entire String and write once.
It depends by what is your situation, in general try to make your code CLEAR.

Related

Bypass error: code too large when initializing byte array [duplicate]

Is there any maximum size for code in Java? I wrote a function with more than 10,000 lines. Actually, each line assigns a value to an array variable.
arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture";
And while compiling, I get this error: code too large
How do I overcome this?
A single method in a Java class may be at most 64KB of bytecode.
But you should clean this up!
Use .properties file to store this data, and load it via java.util.Properties
You can do this by placing the .properties file on your classpath, and use:
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
There is a 64K byte-code size limit on a method
Having said that, I have to agree w/Richard; why do you need a method that large? Given the example in the OP, a properties file should suffice ... or even a database if required.
According to the Java Virtual Machine specification, the code of a method must not be bigger than 65536 bytes:
The value of the code_length item gives the number of bytes in the code array for this method.
The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536.
code_length defines the size of the code[] attribute which contains the actual bytecode of a method:
The code array gives the actual bytes of Java Virtual Machine code that implement the method.
This seems a bit like madness. Can you not initialize the array by reading the values from a text file, or some other data source?
This error sometimes occur due to too large code in a single function...
To solve that error, split that function in multiple functions, like
//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}
Try to refactor your code. There is limit on the size of method in Java.
As mentioned in other answers there is a 64KB of bytecode limit for a method (at least in Sun's java compiler)
Too me it would make more sense to break that method up into more methods - each assigning certain related stuff to the array (might make more sense to use a ArrayList to do this)
for example:
public void addArrayItems()
{
addSculptureItems(list);
...
}
public void addSculptureItems(ArrayList list)
{
list.add("sculptures");
list.add("stonesculpture");
}
Alternatively you could load the items from a static resource if they are fixed like from a properties file
I have run into this problem myself. The solution that worked for me was to refactor and shrink the method to more manageable pieces. Like you, I am dealing with a nearly 10K line method. However, with the use of static variables as well as smaller modular functions, the problem was resolved.
Seems there would be a better workaround, but using Java 8, there is none...
I came to this question because I was trying to solve a similar problem. I wanted to hard code a graph that had 1600 elements into a 2D integer array for performance reasons. I was solving a problem on a leetcode style website and loading the graph data from a file was not an option. The entire graph exceeded the 64K maximum so I could not do a single static run of assignments. I split the assignments across several static methods each below the limit and then called each method one by one.
private static int[][] G = new int[1601][];
static {
assignFirst250();
assignSecond250();
assignSecond500();
assignThird500();
}
private static void assignFirst250() {
G[1] = new int[]{3,8,15,24,35,48,63,80,99,120,143,168,195,224,255,288,323,360,399,440,483,528,575,624,675,728,783,840,899,960,1023,1088,1155,1224,1295,1368,1443,1520,1599};
G[2] = new int[]{2,7,14,23,34,47,62,79,98,119,142,167,194,223,254,287,322,359,398,439,482,527,574,623,674,727,782,839,898,959,1022,1087,1154,1223,1294,1367,1442,1519,1598};
You can add another method to create space for your code for additional data space, you might have a method that is taking a large amount of data space. Try dividing your methods because I had the same issue and and fix it by creating another an additional method for the same data in my java Android code, The issue was gone after I did that.
I have an enum that causes the .java file to be over 500KB in size. Eclipse can build it for some reason; the eclipse-exported ant build.xml cannot. I'm looking into this and will update this post.
this is due to all code in single methods
solution :create more some small methods then this error will be gone
As there is a size limit for methods and you don't want to redesign your code as this moment, may be you can split the array into 4-5 parts and then put them into different methods. At the time of reading the array, call all the methods in a series. You may maintain a counter as well to know how many indexes you have parsed.
ok maybe this answer is too late but I think this way is better than another way so
for example, we have 1000 rows data in code
break them
private void rows500() {
//you shoud write 1-500 rows here
}
private void rows1000() {
you shoud write 500-1000 rows here
}
for better performance put an "if" in your codes
if (count < 500) {
rows500();
} else if (count > 500) {
rows1000();
}
I hope this code helps you

Automate Testing with changing test cases in Java

I am trying to automate testing for a program written in Java. The problem I have is that there needs to be a way to add/remove more tests cases without changing the code.
For example, you have two strings and want to check if they are within a list of strings. You pass the the strings over and check. In Java code, I could make an if statement and check if the two strings match some string in a given list. However, if I wanted to add more strings to search for from that list, I would have to go back to the program and add more code.
Probably a bad example, but I hope you get my point. Of course, there can be many more test cases that might be completely different. And if I wanted to give the program to someone else, they might want to add their own as well.
I was thinking to create some kind of template with arguments and method names to call that's outside of the code. Basically a file with rules. The Java code will then interpret what to do with the given rules. I was reading this: https://blog.codecentric.de/en/2016/01/robot-framework-tutorial-2016-keywords/ but wasn't really understanding it.
My goal is to write some generic Java code that can interpret a template file and run the test cases defined in there. Any help would be appreciated, thank you!
Example:
Template file
Details: Checks if String in database
Method: testID
Arguments: Hello
Foobar.java
public class Foobar {
public void testID(String str1)
{
// Expected output will be taken from a database
Assert.assertEquals(str1, expected_output);
}
}
The String str1 can be taken from the template file under Arguments.
The problem with this is that if I now want to test if str1 is a certain length, I would have to go back and add more code. This would be fine if the program was just for me and my team. However, when you give it to another company or person that doesn't know how to code but they want to run their own tests, it won't be that functional. That's why I was hoping, a person not on the team could just add their test case given they follow the format of the template and the Java program will know what to do with it.
I'm sorry I don't know how to explain it that well. Hope it's not confusing.
As far as I understand your question,
You are looking to give a generic framework to whole lot of users where each of them would want it to use it in there own way!
My friend this is where "Keyword driven framework" come in to picture!
To be more specific as you said you write a function to "check string in a list" but if someone wants to "check the length" then u have to edit your function again!!
All you need to do is analyze the different operations that you have to support.
Say, check for string in list, check length of string, check size of list, check string not in list, add string to list etc.
So instead of you writing a function with mixture of operations! you make it modular instead and give it back to the users to use it in their own way!
So if you declare the above 4 keywords (functions). they can call it in the order they want
e.g. test cases would then look like:
test1:
check for string in list <string1>
test2:
check length of string <string1>
check size of list
check for string not in list <string1>
You define templates for each of these functions and pass on info to users! so that can use these modularized keywords as they want it. This is how robotframework is done!
Hope it is useful!
There are many ways to create and read test resources for use in Java.
You can use straight text strings in .txt files, xml formats, comma delimited formats, etc.
It will really depend on the amount and depth of test data that you are trying to inject.
There are many questions/answers here that you can search for on how using resource files or other file read methods.
Here is an example: How should I load files into my Java application?

"Code too large" -- How can I make a huge, compiled lookup table? [duplicate]

Is there any maximum size for code in Java? I wrote a function with more than 10,000 lines. Actually, each line assigns a value to an array variable.
arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture";
And while compiling, I get this error: code too large
How do I overcome this?
A single method in a Java class may be at most 64KB of bytecode.
But you should clean this up!
Use .properties file to store this data, and load it via java.util.Properties
You can do this by placing the .properties file on your classpath, and use:
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
There is a 64K byte-code size limit on a method
Having said that, I have to agree w/Richard; why do you need a method that large? Given the example in the OP, a properties file should suffice ... or even a database if required.
According to the Java Virtual Machine specification, the code of a method must not be bigger than 65536 bytes:
The value of the code_length item gives the number of bytes in the code array for this method.
The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536.
code_length defines the size of the code[] attribute which contains the actual bytecode of a method:
The code array gives the actual bytes of Java Virtual Machine code that implement the method.
This seems a bit like madness. Can you not initialize the array by reading the values from a text file, or some other data source?
This error sometimes occur due to too large code in a single function...
To solve that error, split that function in multiple functions, like
//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}
Try to refactor your code. There is limit on the size of method in Java.
As mentioned in other answers there is a 64KB of bytecode limit for a method (at least in Sun's java compiler)
Too me it would make more sense to break that method up into more methods - each assigning certain related stuff to the array (might make more sense to use a ArrayList to do this)
for example:
public void addArrayItems()
{
addSculptureItems(list);
...
}
public void addSculptureItems(ArrayList list)
{
list.add("sculptures");
list.add("stonesculpture");
}
Alternatively you could load the items from a static resource if they are fixed like from a properties file
I have run into this problem myself. The solution that worked for me was to refactor and shrink the method to more manageable pieces. Like you, I am dealing with a nearly 10K line method. However, with the use of static variables as well as smaller modular functions, the problem was resolved.
Seems there would be a better workaround, but using Java 8, there is none...
I came to this question because I was trying to solve a similar problem. I wanted to hard code a graph that had 1600 elements into a 2D integer array for performance reasons. I was solving a problem on a leetcode style website and loading the graph data from a file was not an option. The entire graph exceeded the 64K maximum so I could not do a single static run of assignments. I split the assignments across several static methods each below the limit and then called each method one by one.
private static int[][] G = new int[1601][];
static {
assignFirst250();
assignSecond250();
assignSecond500();
assignThird500();
}
private static void assignFirst250() {
G[1] = new int[]{3,8,15,24,35,48,63,80,99,120,143,168,195,224,255,288,323,360,399,440,483,528,575,624,675,728,783,840,899,960,1023,1088,1155,1224,1295,1368,1443,1520,1599};
G[2] = new int[]{2,7,14,23,34,47,62,79,98,119,142,167,194,223,254,287,322,359,398,439,482,527,574,623,674,727,782,839,898,959,1022,1087,1154,1223,1294,1367,1442,1519,1598};
You can add another method to create space for your code for additional data space, you might have a method that is taking a large amount of data space. Try dividing your methods because I had the same issue and and fix it by creating another an additional method for the same data in my java Android code, The issue was gone after I did that.
I have an enum that causes the .java file to be over 500KB in size. Eclipse can build it for some reason; the eclipse-exported ant build.xml cannot. I'm looking into this and will update this post.
this is due to all code in single methods
solution :create more some small methods then this error will be gone
As there is a size limit for methods and you don't want to redesign your code as this moment, may be you can split the array into 4-5 parts and then put them into different methods. At the time of reading the array, call all the methods in a series. You may maintain a counter as well to know how many indexes you have parsed.
ok maybe this answer is too late but I think this way is better than another way so
for example, we have 1000 rows data in code
break them
private void rows500() {
//you shoud write 1-500 rows here
}
private void rows1000() {
you shoud write 500-1000 rows here
}
for better performance put an "if" in your codes
if (count < 500) {
rows500();
} else if (count > 500) {
rows1000();
}
I hope this code helps you

Java - Writing a file using randomAccessFile

I am trying a create a .dat file that is split into 5 columns each with the heading, "timestamp", "deviceId", "testId", "Availability" and "Latency".
This file is going to be pointed to a database where there are tests being ran at the moment.
The idea is that the data from these tests will be collected and stored into this file that I have just created.
I have been told to use and work with RandomAccessFile.
Only problem is I have no idea how to write a file through Java.
I have made somewhat of an attempt but it is by no means much at all;
public long timestamp;
public int deviceId;
public int testId;
public byte availability;
public int latency;
public static void main (String [] args) throws FileNotFoundException
{
String fileName = "hopeToJaysusThisWorks.dat";
RandomAccessFile file = new RandomAccessFile(fileName, "rw");
}
As you can see, its not much at all!
I was told not to worry about getting into the technical side of things yet i.e the collection of data. At the moment all I need is the layout of each column and its 5 headings.
Can anyone help me or give me some advice on where to go from here, it would be much appreciated.
Well the next step for you, would be to make sure the file you just tried to open for reading/writing (that's what the "rw" option means, if you give it just a r or just a w, it's for only reading, or only writing, respectively), is actually open/available. You can do this by simply running a check to see if your 'file' variable is null. Ok great! now you need to actually start writing some information into the file. This can take MANY forms, I recommend checking out the RandomaccessFile api to see exactly what methods are available, and what form you data has to be in to write it.
It'll look something like:
if (file != null){
file.write(myByteArray[]);
}
now, you may have your data structured however, but that's the general gist of it.
Good luck!

Jmock - how to automate & mock out console user input?

I have some functionality that I want to mock out being called from main (static: I've read about that too - jmock mocking a static method). i recently read that JMock doesn't support the mocking of static functions. Well, the associated code (that's giving me a problem) must be called from main, and must be in the class with main...
Sample source
Test code
Right now, I want to ensure that my main has a test to make sure that the file exists before it proceeds. Problem is, I have my program getting user input from the console, so I don't know how to mock that out? Do I just go down to that level of granularity, specifying at every point along the way what happens, so that I can write about only one operation in a function that returns the user's input? I know that to write the tests well, when the tests are run, they should not ask for the user input, I should be specifying it in my tests somehow.
I think it has to do with the following:
How to use JMock to test mocked methods inside a mocked method
I'm not that good with JMock...
If the readInput() method does something, like, say:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
return in.readLine();
Then you might be able to get away with a test that goes something like:
InputStream oldSystemIn = System.in;
InputStream mockSystemIn = context.mock(InputStream.class);
System.setIn(mockSystemIn);
context.checking(new Expectations() {{
// mock expected method calls and return values
}});
// execute
// verify
System.setIn(oldSystemIn);
You can use System Rules instead of mocking System.out and System.in.
public void MyTest {
#Rule
public TextFromStandardInputStream systemInMock = emptyStandardInputStream();
#Test
public void readTextFromStandardInputStream() {
systemInMock.provideText("your file name");
//your code that reads "your file name" from System.in
}
}
Stefan Birkner's answer gave me the direction that I need to be able to solve this. I have posted the code that I used to solve this below.
Solved tests: Birkner's version (recommended)
Solved tests: piped version
Changed source:
WHY: What happens is, with Birkner's library, you can only ever read as much input as you instantiate with the rule originally. If you want to iteratively write to the endpoint, you can do this with a pipe hack, but it doesn't make much of a difference, you can't write to the input over the pipe while the function is actually running, so you might as well use Birkner's version, his #Rule is more concise.
Explanation: In both the pipe hack and with Birkner's code, in the client being tested, multiple calls to create any object that reads from System.in will cause a blocking problem where, once the first object has opened a connection to the Pipe or to System.in, others can not. I don't know why this exactly is for Birkner's code, but with the Pipe I think that it's because you can only open 1 stream to the object-ever. Notice that if you call close on the first buffered reader, and then try to reopen System.in in your client code after having called it from the test, then the second attempt to open will fail because the pipe on the writer's side has been closed as well.
Solution: Easy way to solve this, and probably not the best because it requires modifying the source of the actual project, but not in a horrendous way (yet). So instead of having in the source of the actual project multiple BufferedReader creations, create a buffered reader, and pass the same reader reference around or make it a private variable of the class. Remember that if you have to declare it static that you should not initialize it in a static context because if you do, when the tests run, System.setIn will get called AFTER the reader has been initialized in your client. So it will poll on all readLine/whatever calls, just as it will if you try to create multiple objects from System.in.
Notice that to have your reads segregated between calls from your reader, in this case BufferedReader, you can use newlines to segregate them in the original setup. This way, it returns what you want in each call in the client being tested.

Categories

Resources