Read data from file using Java - java

I have file where every line represents vertice. (format for example- 1.0 0.0 vertice A)
My task is to create method
public void read(InputStream is) throws IOException
Which would save X and Y values of vertices and then label of it "vertice A". I have no idea how to parse it properly:
public void read(InputStream is) throws IOException {
try {
Reader r = new InputStreamReader(is);
BufferedReader br = new BufferedReader(r);
while(br.readLine()!=null){
//something
}
} catch(IOException ex){
ex.printStackTrace();
}
}
also I need to create method
public void read(File file) throws IOException
which makes exactly the same but with file instead of stream. Can you tell me difference between these two methods?

A File represents a node on the filesystem, a stream is a representation of a sequence of data with a read head. Opening a file for reading results in an input stream. System.In is an example of an input stream for which you did not provide a file, it is the stream for stdin.
public void read(File file) throws IOException
{
//using your input stream method, read the passed file
//Create an input stream from the given file, and then call what you've already implemented.
read(new FileInputStream(file));
//I assume your read function closes the stream when it's done
}

I'd do the following and explain it through the code :)
public void read(InputStream is) throws IOException {
//You create a reader hold the input stream (sequence of data)
//You create a BufferedReader which will wrap the input stream and give you methods to read your information
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
handleVerticeValues(reader);
reader.close();
}
public void read(File file) throws IOException {
//You create a buffered reader to manipulate the data obtained from the file representation
BufferedReader reader = new BufferedReader(new FileReader(file));
handleVerticeValues(reader);
reader.close();
}
private void handleVerticeValues(BufferedReader reader) throws IOException {
//Then you can read your file like this:
String lineCursor = null;//Will hold the value of the line being read
//Assuming your line has this format: 1.0 0.0 verticeA
//Your separator between values is a whitespace character
while ((lineCursor = reader.readLine()) != null) {
String[] lineElements = lineCursor.split(" ");//I use split and indicates that we will separate each element of your line based on a whitespace
double valX = Double.parseDouble(lineElements[0]);//You get the first element before an whitespace: 1.0
double valY = Double.parseDouble(lineElements[1]);//You get the second element before and after an whitespace: 0.0
String label = lineElements[2];//You get the third element after the last whitespace
//You do something with your data
}
}
You can avoid using split by using StringTokenizer as well, that is another approach :).
As mentioned in the other answer, a file is only a representation of a node in your file system, it just point to an element existing in your file system but it not hold any data or information at this point of your internal file, I mean, just information as a file (if is a file, directory or something like that) (if it does not exist, you receive a FileNotFoundException).
The InputStream is a sequence of data, at this point, you should have information here which needs to be handled or read by a BufferedReader, ObjectInputStream or another component, depending on what you need to do.
For more info, you can also ask to your friendly API docs:
https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html
https://docs.oracle.com/javase/7/docs/api/java/io/File.html
Regards and... happy coding :)

Related

How to replace specific String in a text file by java?

I'm writing a program with a text file in java, what I need to do is to modify the specific string in the file.
For example, the file has a line(the file contains many lines)like "username,password,e,d,b,c,a"
And I want to modify it to "username,password,f,e,d,b,c"
I have searched much but found nothing. How to deal with that?
In general you can do it in 3 steps:
Read file and store it in String
Change the String as you need (your "username,password..." modification)
Write the String to a file
You can search for instruction of every step at Stackoverflow.
Here is a possible solution working directly on the Stream:
public static void main(String[] args) throws IOException {
String inputFile = "C:\\Users\\geheim\\Desktop\\lines.txt";
String outputFile = "C:\\Users\\geheim\\Desktop\\lines_new.txt";
try (Stream<String> stream = Files.lines(Paths.get(inputFile));
FileOutputStream fop = new FileOutputStream(new File(outputFile))) {
stream.map(line -> line += " manipulate line as required\n").forEach(line -> {
try {
fop.write(line.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
You can try like this:
First, read the file line by line and check each line if the string you want to replace exists in that, replace it, and write the content in another file. Do it until you reach EOF.
import java.io.*;
public class Files {
void replace(String stringToReplace, String replaceWith) throws IOException {
BufferedReader in = new BufferedReader(new FileReader("/home/asn/Desktop/All.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("/home/asn/Desktop/All-copy.txt"));
String line;
while((line=in.readLine())!=null) {
if (line.contains(stringToReplace))
line = line.replace(stringToReplace, replaceWith);
out.write(line);
out.newLine();
}
in.close();
out.close();
}
public static void main(String[] args) throws IOException {
Files f = new Files();
f.replace("amount", "####");
}
}
If you want to use the same file store the content in a buffer(String array or List) and then write the content of the buffer in the same file.
If your file look similar to this:
username:username123,
password:password123,
After load file to String you can do something like this:
int startPosition = file.indexOf("username") + 8; //+8 is length of username with colon
String username;
for(int i=startPosition; i<file.length(); i++) {
if(file.charAt(i) != ',') {
username += Character.toString(file.charAt(i));
} else {
break;
}
System.out.println(username); //should prong username
}
After edit all thing you want to edit, save edited string to file.
There are much ways to solve this issue. Read String docs to get to know operations on String. Without your code we cannot help you enough aptly.
The algorithm is as follows:
Open a temporary file to save edited copy.
Read input file line by line.
Check if the current line needs to be replaced
Various methods of String class may be used to do this:
equals: Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
equalsIgnoreCase: Compares this String to another String, ignoring case considerations.
contains: Returns true if and only if this string contains the specified sequence of char values.
matches (String regex): Tells whether or not this string matches the given regular expression.
startsWith: Tests if this string starts with the specified prefix (case sensitive).
endsWith: Tests if this string starts with the specified prefix (case sensitive).
There are other predicate functions: contentEquals, regionMatches
If the required condition is true, provide replacement for currentLine:
if (conditionMet) {
currentLine = "Your replacement";
}
Or use String methods replace/replaceFirst/replaceAll to replace the contents at once.
Write the current line to the output file.
Make sure the input and output files are closed when all lines are read from the input file.
Replace the input file with the output file (if needed, for example, if no change occurred, there's no need to replace).

What is the preferred way of piping information into another process in Java?

I need to pipe data into another process. The data is an array of strings that I concatenated into one large string. The external process accepts a text file. Currently, I am writing the string into a ByteArrayOutputStream but is there a better way to do this?
public OutputStream generateBoxFile() throws IOException {
OutputStream boxStream = new ByteArrayOutputStream();
for (String boxLine : boxLines) {
boxLine += "\n";
boxStream.write(boxLine.getBytes(Charset.forName("UTF-8")));
}
return boxStream;
}
EDIT: For further clarifications, I am launching a program called trainer which accepts a text file. So I would invoke this program like this in the shell ./trainer textfile. However, I want to do everything in memory, so I'm looking for a good way to write data into a temporary file that is not on disk and then feed this into trainer.
The simplest way to write a collection String to a file is to use a PrintWriter
public static void writeToFile(String filename, Iterable<String> strings) {
try (PrintWriter pw = new PrintWriter(filename)) {
for(String str : strings)
pw.println(str);
}
}
If you need to write UTF-8 you can change the encoding with
try (PrintWriter pw = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(filename), "UTF-8")) {
You can easily pipe data to a process you've launched through its standard input stream. In the parent process, you can access the child's standard input stream through Process.getOutputStream().
This does require your child process to accept data through standard input rather than a file. Your child process currently gets its input from a file. Fortunately, you note in a comment that you own the code of the child process.

Safe implementation of BufferdReader

I want to use a BufferedReader to read a file uploaded to my server.
The file would by written as a CSV file, but I can't assume this, so I code some test where the file is an image or a binary file (supposing the client has sent me the wrong file or an attacker is trying to break my service), or even worse, the file is a valid CSV file but has a line of 100MB.
My application can deal with this problem, but it has to read the first line of the file:
...
String firstLine = bufferedReader.readLine();
//Perform some validations and reject the file if it's not a CSV file
...
But, when I code some tests, I've found a potential risk: BufferedReader doesn't perform any control over the amount of bytes it reads until it found a return line, so it can ended up throwing an OutOfMemoryError.
This is my test:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import org.junit.Test;
public class BufferedReaderTest {
#Test(expected=OutOfMemoryError.class)
public void testReadFileWithoutReturnLineCharacter() throws IOException {
BufferedReader bf = new BufferedReader(getInfiniteReader());
bf.readLine();
bf.close();
}
private Reader getInfiniteReader() {
return new Reader(){
#Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 'A';
}
#Override
public void close() throws IOException {
}
};
}
}
I've been looking up some safe BufferedReader implementation on the internet, but I can't find anything. The only class I've found was BoundedInputStream from apache IO, that limits the amount of bytes read by an input stream.
I need an implementation of BufferedReader that knows how to limit the number of bytes/characters read in each line.
Something like this:
The app calls 'readLine()'
The BufferedReader reads bytes until it found a return line character or it reaches the maximum amount of bytes allowed
If it has found a return line character, then reset the bytes read (so it could read the next line) and return the content
If it has reached the maximum amount of bytes allowed, it throws an exception
Does anybody knows about an implementation of BufferedReader that has this behaviour?
This is not how you should proceed to detect whether a file is binary or not.
Here is how you can do to check whether a file is truly text or not; note that this requires that you know the encoding beforehand:
final Charset cs = StandardCharsets.UTF_8; // or another
final CharsetDecoder decoder = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT); // default is REPLACE!
// Here, "in" is the input stream from the file
try (
final Reader reader = new InputStreamReader(in, decoder);
) {
final char[] buf = new char[4096]; // or other size
while (reader.read(buf) != -1)
; // nothing
} catch (MalformedInputException e) {
// cannot decode; binary, or wrong encoding
}
Now, since you can initialize a BufferedReader over a Reader, you can use:
try (
final Reader r = new InputStreamReader(in, decoder);
final BufferedReader reader = new BufferedReader(r);
) {
// Read lines normally
} catch (CharacterCodingException e) {
// Not a CSV, it seems
}
// etc
Now, a little more explanation about how this works... While this is a fundamenal part of reading text in Java, it is a part which is equally fundamentally misunderstood!
When you read a file as text using a Reader, you have to specify a character coding; in Java, this is a Charset.
What happens internally is that Java will create a CharsetDecoder from that Charset, read the byte stream and output a char stream. And there are three ways to deal with errors:
CodingErrorAction.REPLACE (the default): unmappable byte sequences are replaced with the Unicode replacement character (it does ring a bell, right?);
CodingErrorAction.IGNORE: unmappable byte sequences do not trigger the emission of a char;
CodingErrorAction.REPORT: unmappable byte sequences trigger a CharacterCodingException to be thrown, which inherits IOException; in turn, the two subclasses of CharacterCodingException are MalformedInputException and UnmappableCharacterException.
Therefore, what you need to do in order to detect whether a file is truly text is to:
know the encoding beforehand!
use a CharsetDecoder configured with CodingErrorAction.REPORT;
use it in an InputStreamReader.
This is one way; there are others. All of them however will use a CharsetDecoder at some point.
Similarly, there is a CharsetEncoder for the reverse operation (char stream to byte stream), and this is what is used by the Writer family.
Thank you #fge for the answer. I ended up implementing a safe Readerthat can deal with files with too long lines (or without lines at all).
If anybody wants to see the code, the project (very small project even with many tests) is available here:
https://github.com/jfcorugedo/security-io

Reading data from text line by line in java

I'm making a game in Java, but can't figure out how to get information from a text file so that I can load the game. I have the saved files set up so that on every line there is the name of a method in my Main program. What I need to do is to look in a certain line for text and execute the method that the text is referring to.
This should do it. Obviously you'll need to handle exceptions:
public class FileReaderTest
{
public static void main(String[] args) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
final FileReaderTest object = new FileReaderTest();
final BufferedReader reader = new BufferedReader(new FileReader(new File("/path/to/file")));
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
object.getClass().getMethod(line).invoke(object);
}
}
}
Now, this is assuming that you are talking about a .txt file.
I/O is the basic Idea, If you master that, then you are set. I stands for input, and O, for Output.
Now, you need to make an variable equal to inputStream.readInt();
EDIT:
But for more help, you can also go with reading
Reading a text file in java
Hope this helps!

Most concise way to read the contents of a file/input stream in Java?

What ist most concise way to read the contents of a file or input stream in Java? Do I always have to create a buffer, read (at most) line by line and so on or is there a more concise way? I wish I could do just
String content = new File("test.txt").readFully();
Use the Apache Commons IOUtils package. In particular the IOUtils class provides a set of methods to read from streams, readers etc. and handle all the exceptions etc.
e.g.
InputStream is = ...
String contents = IOUtils.toString(is);
// or
List lines = IOUtils.readLines(is)
I think using a Scanner is quite OK with regards to conciseness of Java on-board tools:
Scanner s = new Scanner(new File("file"));
StringBuilder builder = new StringBuilder();
while(s.hasNextLine()) builder.append(s.nextLine());
Also, it's quite flexible, too (e.g. regular expressions support, number parsing).
Helper functions. I basically use a few of them, depending on the situation
cat method that pipes an InputStream to an OutputStream
method that calls cat to a ByteArrayOutputStream and extracts the byte array, enabling quick read of an entire file to a byte array
Implementation of Iterator<String> that is constructed using a Reader; it wraps it in a BufferedReader and readLine's on next()
...
Either roll your own or use something out of commons-io or your preferred utility library.
To give an example of such an helper function:
String[] lines = NioUtils.readInFile(componentxml);
The key is to try to close the BufferedReader even if an IOException is thrown.
/**
* Read lines in a file. <br />
* File must exist
* #param f file to be read
* #return array of lines, empty if file empty
* #throws IOException if prb during access or closing of the file
*/
public static String[] readInFile(final File f) throws IOException
{
final ArrayList lines = new ArrayList();
IOException anioe = null;
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader(f));
String line;
line = br.readLine();
while(line != null)
{
lines.add(line);
line = br.readLine();
}
br.close();
br = null;
}
catch (final IOException e)
{
anioe = e;
}
finally
{
if(br != null)
{
try {
br.close();
} catch (final IOException e) {
anioe = e;
}
}
if(anioe != null)
{
throw anioe;
}
}
final String[] myStrings = new String[lines.size()];
//myStrings = lines.toArray(myStrings);
System.arraycopy(lines.toArray(), 0, myStrings, 0, lines.size());
return myStrings;
}
(if you just want a String, change the function to append each lines to a StringBuffer (or StringBuilder in java5 or 6)
String content = (new RandomAccessFile(new File("test.txt"))).readUTF();
Unfortunately Java is very picky about the source file being valid UTF8 though, or you will get an EOFException or UTFDataFormatException.
You have to create your own function, I suppose. The problem is that Java's read routines (those I know, at least) usually take a buffer argument with a given length.
A solution I saw is to get the size of the file, create a buffer of this size and read the file at once. Hoping the file isn't a gigabyte log or XML file...
The usual way is to have a fixed size buffer or to use readLine and concatenate the results in a StringBuffer/StringBuilder.
I don't think reading using BufferedReader is a good idea because BufferedReader will return just the content of line without the delimeter. When the line contains nothing but newline character, BR will return a null although it still doesn't reach the end of the stream.
String org.apache.commons.io.FileUtils.readFileToString(File file)
Pick one from here.
How do I create a Java string from the contents of a file?
The favorite was:
private static String readFile(String path) throws IOException {
FileInputStream stream = new FileInputStream(new File(path));
try {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* Instead of using default, pass in a decoder. */
return CharSet.defaultCharset().decode(bb).toString();
}
finally {
stream.close();
}
}
Posted by erickson
Or the Java 8 way:
try {
String str = new String(Files.readAllBytes(Paths.get("myfile.txt")));
...
} catch (IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
One may pass an appropriate Charset to the String constructor.

Categories

Resources