'Inheriting' function parameters - java

I think this is kinda language-agnostic, but I'd like to know how this feature works in Java.
Let's suppose I have a function that reads a file using a Scanner:
void printFile(Scanner s) {
while (s.hasNextLine()) {
String line = s.nextLine();
System.out.println(line);
}
}
So, if I have several ways to simulate a file, using this function would be
String content = "foo\nbar\n";
printFile(new Scanner(content));
File file = new File("my/file.txt");
printFile(new Scanner(file));
InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
printFile(new Scanner(input));
My question is, if I have several ways to simulate this file, how do I make it easier to use this function without having to enter new Scanner() every time I call it?
Some observations:
This would be useful in two ways: ease of writing unit tests and simplifying the API for the user.
Overloading the function solves the problem, however if the original function has several overloads, this could make the code ugly and/or complicate writing code, where the developer would have to read the documentation, write a corresponding overload and repeat.

Related

Java: What's the most efficient way to read relatively large txt files and store its data?

I was supposed to write a method that reads a DNA sequence in order to test some string matching algorithms on it.
I took some existing code I use to read text files (don't really know any others):
try {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null) {
seq += line;
}
br.close();
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
This seems to work just fine for small text files with ~3000 characters, but it takes forever (I just cancelled it after 10 minutes) to read files containing more than 45 million characters.
Is there a more efficient way of doing this?
One thing I notice is that you are doing seq+=line. seq is probably a String? If so, then you have to remember that strings are immutable. So in fact what you are doing is creating a new String each time you are trying to append a line to it. Please use StringBuilder instead. Also, if possible you don't want to do create a string and then process. That way you have to do it twice. Ideally you want to process as you read, but I don't know your situation.
The main element slowing your progress is the "concatenation" of the String seq and line when you call seq+=line. I use quotes for concatenation because in Java, Strings cannot be modified once they are created (e.g. immutable as user1598503 mentioned). Initially, this is not an issue, as the Strings are small, however once the Strings become very long, e.e. hundreds of thousands of characters, memory must be reallocated for the new String, which takes quite a bit of time. StringBuilder will allow you to do these concatenations in place, meaning you will not be creating a new Object every single time.
Your problem is not that the reading takes too much time, but the concatenating takes too much time. Just to verify this I ran your code (didn't finish) and then simply comented line 8 (seq += line) and it ran in under a second. You could try using seq = seq.concat(line) since it has been reported to be quite a bit faster most of the times, but I tried that too and didn't ran under 1-2 minutes (for a 9.6mb input file). My solution would be to store your lines in an ArrayList (or a container of your choice). The ArrayList example worked in about 2-3 seconds with the same input file. (so the content of your while loop would be list.add(line);). If you really, really want to store your entire file in a string you could do something like this (using the Scanner class):
String content = new Scanner(new File("input")).useDelimiter("\\Z").next();
^^This works in a matter of seconds as well. I should mention that "\Z" is the end of file delimiter so that's why it reads the whole thing in one swoop.

What is C++ equivalent of Java StdIn.isEmpty()

I am trying to learn something basing on Java resource, and I want to adapt it to C++.
Source of Java has:
while( !StdIn.isEmpty())
{
//Take input from standard input, and process it...
}
In C++ the closest solution I could come up with was
while( cin >> someString)
{
//process someString...
}
However, the problem is, that cin returns state of object. There is no way I can put wrong input into std::string. This could have worked for ints, but not for string. Any equivalent function, or workarounds?
Thanks in advance.
With C++ iostreams, and also with C's stdio, you cannot tell whether a file (such as std::cin/stdin) will be empty if you were to try reading from it. The only way to find out is to actually read from the file, and then check whether the attempt succeeded.
(Yes, you could use some form of peek, but that's nowhere near as idiomatic or practical.)
So a standard method in C++ might look like this, processing entire lines of input at a time:
for (std::string line; std::getline(std::cin, line); )
{
// process "line"
}
The loop body will only execute if you succeeded at extracting one line from the input. Once the input runs out of data, the loop condition is no longer satisfied (i.e. the stream is no longer "good"), and the loop stops.
The same idea applies to C's fgets, as well as to unformatted std::istream::read() and fread, and to platform-specific functions like Posix's read(2): You always attempt to obtain input, then check whether you got any input, and only if you did do you proceed to consume the input.

JUnit Command Line Testing

This has been asked before, but was not clarified to the point where I get it. Similar to the one or two other threads I've seen on this subject, I'm working on a chat client with command line inputs for logging in/off, disconnecting, etc. and I am unsure how to simulate this in a JUnit test case. Other responses indicated that I should try changing the System.in to a separate InputStream but...then what?
tl;dr: I have a method in my actual code for parsing command line input, and need a JUnit way of testing that these were entered and appropriately processed.
EDIT: It seems I misunderstood the question. I usually use the term "command line input" to refer to command line arguments given to the process to start with, rather than interactive console input. However...
Handing your real code either a different InputStream or possibly even a Reader or Scanner would indeed help - anything to separate the "getting input" part from the console. You can then fake the input all in one go pretty easily, using a String as input in your test code, and then either converting it to bytes and wrapping those bytes in a ByteArrayInputStream or wrapping the string directly in StringReader.
The downside of this is that there's no easy way of making this "pause" after one command in order to check the results.
You may want to alter the design somewhat so that the part which reads the input is separated from the part which handles the input. The reading part could be a very simple loop, on the order of:
String line;
while ((line = reader.readLine()) != null) {
handleInput(line);
}
You could then potentially leave that part untested by unit tests, or write some relatively primitive tests - but you can then test handleInput extensively, as it's now separated from the input source.
Original answer
If you've extracted the parsing code from the code which really starts the application, it's easy: run that code, and check the results. This will be easiest if you have some sort of class encapsulating the options, of course. For example, your main method might look like this:
public static void main(String[] args) {
Options options = Options.parse(args);
// Use options here
}
Then you can just test Options.parse very easily.

How do i read a notepad file in java? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
im trying to create a restaurant system that will create food items and such from a menu.
ill be learning jdbc soon and im sure that would help but for now i think the simplest way is too create my menu in notepad.
whats the best way to line up and read from a notepad file like a menu.
please try speak clearly, im not exactly sure of all terminologies.
this one looks promising but ive no idea whats goin on.
/////////////////////////////////////////////////////////////////////
im still stuck with this.
ive decided too make a seperate mthod for reading the file.
ive tried every example i can think of. could someone just show me an example of how too define a files classpath.
if i type menu.txt it just doesnt work.
Have a look at Sun's Java Tutorial
Easiest option is to simply use the Apache Commons IO JAR and import the org.apache.commons.io.FileUtils class. There are many possibilities when using this class, but the most obvious would be as follows;
List<String> lines = FileUtils.readLines(new File("untitled.txt"));
It's that easy.
"Don't reinvent the wheel."
Can I ask what sort of content/data you will be reading from this file as there may be other (even simpler) possibilities?
i.e.
Properties
foo="bar"
String Tokens
foo,bar,fu,baz
Let me know if you require more details with any of the processes I've mentioned.
http://java.sun.com/j2se/1.5.0/docs/api/java/io/BufferedReader.html#readLine()
"Notepad" files are just text files, so you just read it in with a a Reader instance. Since Notepad supports windows Unicode, you may need to specify a charset of "UTF-16LE".
String filename = "myfile.txt";
BufferedReader reader = new BufferedReader(new FileReader(filename));
try{
String line;
//as long as there are lines in the file, print them
while((line = reader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
The basic idea is that you create a file reader object
FileReader fr = new FileReader('file.txt');
and then go over the file line by line parsing each line and saving the stuff to some internal data storage (Array, HashMap).
The while loop in the example you have does just this. The FileReader class will take care of the line ending for you, and will return null when there's no more lines to be read. What you need to do inside the while loop is to parse each line and separate the different bits of data (course name, price etc.) from each other.
EDIT: To parse the lines you would do something like the following. What is inside the while loop depends on how you format the menu files. The following works on the assumption that the menu files contains the price and the name of the course (in that order) separated by a comma on each line.
12.95$,Penne ala Arabiata
8.15$,Fish Soup
Notice that you can't use a comma in the price if you do this. You can of course use a semicolon as the separator between the data fields instead of a comma. The number of data fields is of course also up to you.
String line = "";
// read lines from file
while ((line = fr.readLine()) != null) {
// parse each line
tokens = line.split(",");
String price = tokens[0];
String courseName = tokens[1];
// extract all other information
}
In your final code you'll want to save the data fields into some structure instead of just extracting them from the file. Another thing to note is that the price is a String NOT a number because of the dollar sign. Should you wish to do any calculations with the prices you'll of course need the convert it to a number with parseFloat() or parseDouble().
And of course if you do use the csv (comma separated values) format, it's better to go for a csv library to do the parsing for you instead of writing the parser yourself.
http://opencsv.sourceforge.net/

What is the fastest method for reading from a text file in Java?

I currently use:
BufferedReader input = new BufferedReader(new FileReader("filename"));
Is there a faster way?
While what you've got isn't necessarily the absolute fastest, it's simple. In fact, I wouldn't use quite that form - I'd use something which allows me to specify a charset, e.g.
// Why is there no method to give this guaranteed charset
// without "risk" of exceptions? Grr.
Charset utf8 = Charset.forName("UTF-8");
BufferedReader input = new BufferedReader(
new InputStreamReader(
new FileInputStream("filename"),
utf8));
You can probably make it go faster using NIO, but I wouldn't until I'd seen an actual problem. If you see a problem, but you're doing other things with the data, make sure they're not the problem first: write a program to just read the text of the file. Don't forget to do whatever it takes on your box to clear file system caches between runs though...
If it's /fast/ you want, keep the character data in encoded form (and I don't mean UTF-16). Although disc I/O is generally slow (unless it's cached), decoding and keeping twice the data can also be a problem. Although the fastest to load is probably through java.nio.channels.FileChannel.map(MapMode.READ_ONLY, ...), that has severe problems with deallocation.
Usual caveats apply.
Look into java.nio.channels.FileChannel.
Have you benchmarked your other options? I imagine that not using a BufferedReader may be faster in some cases - like extremely small files. I would recommend that you at the very least do some small benchmarks and find the fastest implementation that works with your typical use cases.
Depends on what you want to read. The complete file, or from a specific location, do you need to able to seatch through it, or do you want to read the complete text in one go?
File file = new File("querySourceFileName");
Scanner s = new Scanner(file);
while (s.hasNext()) {
System.out.println(s.nextLine());
}

Categories