Java: trash in input Stream - java

I worte a small java function that calls another Java program and displays its input.
private static void call() throws Exception
{
int line;
///Other stuff here
Process p2= Runtime.getRuntime().exec("java SelfModifying");
InputStream is = p2.getInputStream();
//p.waitFor();
while ((line = is.read()) != -1) {
System.out.println("result: " + line);
}
Runtime.getRuntime().exit(0);
}
The prorgam that gests called is supposed to return a single int value: '10'.
Instead, I get 4 lines:
result: 49
result: 48
result: 13
result: 10
Where do the three other values come from? They are deterministic but seem to come from the input. When I run the program on its own it does not return these 3 lines.

You're reading individual bytes from the stream:
49 is ASCII '1';
48 is ASCII '0';
13 is ASCII '\r';
10 is ASCII '\n'.
So the contents of the file is 10\r\n (10, followed by a windows newline).
You should wrap is in a scanner:
Scanner scanner = new Scanner(is, "UTF-8");
System.out.println(scanner.nextInt());

Related

Reading all the values (int)of a RandomAccessFile

I want to read all the information from a randomaccessfile containing integers, with 1 integer a line. eg. It seems to be a problem with my "reading" code.
File Contents:
1
3
5
72
0
My current code gives me an EOFException error and the data that I take in is not correct eg 1 is printed as 857222 etc.
Output:
822751754
856306698
805975306
856306186
java.io.EOFException
822751754
while((tmp = randomFile.readInt()) != -1){
System.out.println(tmp)
}
readInt() and "1 integer a line" don't match.
Either you have a binary file containing bytes that can be read using readInt() (which reads always four bytes for an integer), or you have lines of text where each line contains a readable representation of integer values (which seems to be your case).
To read lines of text containing integer values, you have to rewrite your code like this:
String line;
while ((line = randomFile.readLine()) != null) {
int tmp = Integer.parseInt(line);
System.out.println(tmp);
}
When a RandomAccessFile gets to the end of a file, .nextInt() won't return -1, it will throw an EOFException. Therefore you should do something like this:
while(true){
try{
tmp = randomFile.readInt()
System.out.println(tmp)
}catch(EOFException e){
break;
}
}

Anyone understand external files well?

I am supposed to create a program that reads an external file with 3 integers on every line and find the area of a triangle with those three numbers. We haven't learned arrays yet though, so i want to create the program without an array, methods and classes are fine. I just need help reading the file every three numbers by line.
The data is:
7 8 9
9 9 12
6 5 21
24 7 25
13 12 5
50 40 30
10 10 10
82 34 48
4 5 6
Here's what i have so far:
import java.io.*;
import java.util.*;
import java.lang.*;
public class Prog610a
{
public static void main(String[] args) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader("myData.in"));
String currentLine;
int a, b, c;
double s, area;
System.out.println("A" + "\t B" + "\t C" + "\t Area");
try
{
while((currentLine = reader.readLine()) != null)
{
Scanner scanner = new Scanner(currentLine);
s = ((scanner.nextInt() + scanner.nextInt() + scanner.nextInt()) / 2);
area = Math.sqrt(s * (s - scanner.nextInt()) * (s - scanner.nextInt()) * (s - scanner.nextInt()) );
if(s < 0)
{
System.out.println(scanner.nextInt() + " \t" + scanner.nextInt() +
" \t" + scanner.nextInt() + "\t This is not a triangle");
}
else
{
System.out.println(scanner.nextInt() + " \t" + scanner.nextInt() +
" \t" + scanner.nextInt() + " \t" + area);
}
}
}
finally
{
reader.close();
}
}
}
You have made a good start by using the Scanner. I would suggest that just using that may be insufficient, as you may end up with some malformed lines. To handle them you may wish to split the processing into two parts: get a line, and then get the individual values from that line.
That allows you to catch lines that do not have enough values, or have too many values. If you do not do this then you may become mis-aligned with the lines, reading some values from one line, and some from the following line.
The BufferedReader will allow you to read lines which you can then scan. Since you don't want to use arrays you must extract the numbers individually:
BufferedReader reader = new BufferedReader(new FileReader("myData.in"));
String currentLine;
try {
while ((currentLine = reader.readLine()) != null) {
Scanner scanner = new Scanner(currentLine);
try {
calculateTriangleArea(
scanner.nextInt(), scanner.nextInt(), scanner.nextInt()
);
}
catch (NoSuchElementException e) {
// invalid line
}
}
}
finally {
reader.close();
}
Also it may help you to understand the Java string interpolation. You have horizontalTab throughout your code. You can express that in a string by just using \t. For example:
"\tThis is indented by one tab"
"This is not"
You can find the complete list of string escape characters here.
The exception handling (or lack of) in my code may surprise you. In your code you catch the Exception that could be thrown. However you discard it and then proceed to execute the rest of the code on a Scanner that is known to be broken. In such a situation it is better to fail immediately rather than conceal the error and attempt to proceed.
The one bit of exception handling that does occur in my code is the finally block. This ensures that the reader is closed no matter what happens when reading from it. It wraps the code that is executed after the reader has been opened, and as such it is known that the reader is not null and should be closed after use.

How to read multiple lines using FileReader only?

I have the following code:
public class Reader {
public static void main(String[] args) throws IOException {
try (FileReader in = new FileReader("D:/test.txt")) {
// BufferedReader br = new BufferedReader(in);
int line = in .read();
for (int i = 0; i < line; i++) {
//System.out.println(line);
System.out.println((char) line);
line = in .read();
}
}
}
}
and a file Test.txt with the content:
Hello
Java
When I run above code it only reads Hello. I would like to read multiple lines using FileReader only. I don't want to use BufferedReader or InputStreamReader etc. Is that possible?
I don't think this version of the code prints "Hello".
You are calling:
int line = in.read();
What does this do? Look in the Javadocs for Reader:
public int read()
throws IOException
Reads a single character. This method will block until a character is available, an I/O error occurs, or the end
of the stream is reached.
(emphasis mine)
Your code reads the 'H' from 'Hello', which is 72 in ASCII.
Then it goes into your loop, with line==72, so it goes into the loop:
for(int i=0;i<line;i++)
... making the decision "is 0 less than 72? Yes, so I'll go into the loop block".
Then each time it reads a character the value of line changes to another integer, and each time loop goes around i increments. So the loop says "Keep going for as long as the ASCII value of the character is greater than the number of iterations I've counted".
... and each time it goes around, it prints that character on a line of its own.
As it happens, for your input, it reads end-of-file (-1), and as -1 < i, the loop continue condition is not met.
But for longer inputs it stop on the first 'a' after the 97th character, or the first 'b' after the 98th character, and so on (because ASCII 'a' is 97, etc.)
H
e
l
l
o
J
a
v
a
This isn't what you want:
You don't want your loop to repeat until i >= "the character I just read". You want it to repeat until in.read() returns -1. You have probably been taught how to loop until a condition is met.
You don't want to println() each character, since that adds newlines you don't want. Use print().
You should also look at the Reader.read(byte[] buffer) method, and see if you can write the code to work in bigger chunks.
Two patterns you'll use over and over again in your programming career are:
Type x = getSomehow();
while(someCondition(x)) {
doSomethingWith(x);
x = getSomehow();
}
... and ...
Type x = value_of_x_which_meets_condition;
while(someCondition(x)) {
x = getSomehow();
doSomethingWith(x);
}
See if you can construct something with FileReader and the value you get from it, filling in the "somehows".
Reading file character by character without any buffering stream is extremely ineffective. I would probably wrap FileReader in some BufferedReader or simply used Scanner to read condent of file, but if you absolutely want/need/have to use only FileReader then you can try with
int line = in.read();
while (line != -1) {
System.out.print((char) line);
line = in.read();
}
instead of your for (int i = 0; i < line; i++) {...} loop.
Read carefully slims answer. In short: reading condition shouldn't care if number of characters you read is less then numeric representation of currently read character (i < line). Like in case of
My name
is
not important now
This file has few characters which you normally will not see like \r and \n and in reality it looks like
My name\r\n
\r\n
is\r\n
\r\n
not important now
where numeric representation of \r is 10, so after you read My name\r\n (which is 9 characters because \r and \n are single character representing line separator) your i will become 10 and since next character you will try to read is \r which is also represented by 10 your condition i<line will fail (10<10 is not true).
So instead of checking i<line you should check if read value is not EoF (End of File, or End of Stream in out case) which is represented by -1 as specified in read method documentation so your condition should look like line != -1. And because you don't need i just use while loop here.
Returns:
The character read, or -1 if the end of the stream has been reached
You will have to read the content char by char and parse for a new line sequence.
A new line sequence can be any of the following:
a single cariage return '\r'
a single line feed '\n'
a carriage return followed by a line feed "\r\n"
EDIT
You could try the following:
public List<String> readLinesUsingFileReader(String filename) throws IOException {
List<String> lines = null;
try (FileReader fileReader = new FileReader(filename)) {
lines = readLines(fileReader);
}
return lines;
}
private List<String> readLines(FileReader fileReader) throws IOException {
List<String> lines = new ArrayList<>();
boolean newLine = false;
int c, p = 0;
StringBuilder line = new StringBuilder();
while(-1 != (c = fileReader.read())) {
if(c == '\n' && p != '\r') {
newLine = true;
} else if(c == '\r') {
newLine = true;
} else {
if(c != '\n' && c != '\r') {
line.append((char) c);
}
}
if(newLine) {
lines.add(line.toString());
line = new StringBuilder();
newLine = false;
}
p = c;
}
if(line.length() > 0) {
lines.add(line.toString());
}
return lines;
}
Note that the code above reads the whole file into a List, this might not be well suited for large files! You may want in such a case to implement an approach which uses streaming, i.e. read one line at a time, for example String readNextLine(FileReader fileReader) { ... }.
Some basic tests:
Create test files to read
private final static String txt0 = "testnl0.txt";
private final static String txt1 = "testnl1.txt";
private final static String txt2 = "testnl2.txt";
#BeforeClass
public static void genTestFile() throws IOException {
try (OutputStream os = new FileOutputStream(txt0)) {
os0.write((
"Hello\n" +
",\r\n" +
"World!" +
"").getBytes());
}
try (OutputStream os = new FileOutputStream(txt1)) {
os.write((
"\n" +
"\r\r" +
"\r\n" +
"").getBytes());
}
try (OutputStream os = new FileOutputStream(txt2)) {
os.write((
"").getBytes());
}
}
Test using the created files
#Test
public void readLinesUsingFileReader0() throws IOException {
List<String> lines = readLinesUsingFileReader(txt0);
Assert.assertEquals(3, lines.size());
Assert.assertEquals("Hello", lines.get(0));
Assert.assertEquals(",", lines.get(1));
Assert.assertEquals("World!", lines.get(2));
}
#Test
public void readLinesUsingFileReader1() throws IOException {
List<String> lines = readLinesUsingFileReader(txt1);
Assert.assertEquals(4, lines.size());
Assert.assertEquals("", lines.get(0));
Assert.assertEquals("", lines.get(1));
Assert.assertEquals("", lines.get(2));
Assert.assertEquals("", lines.get(3));
}
#Test
public void readLinesUsingFileReader2() throws IOException {
List<String> lines = readLinesUsingFileReader(txt2);
Assert.assertTrue(lines.isEmpty());
}
If you have the new line character
public static void main(String[]args) throws IOException{
FileReader in = new FileReader("D:/test.txt");
char [] a = new char[50];
in.read(a); // reads the content to the array
for(char c : a)
System.out.print(c); //prints the characters one by one
in.close();
}
It will print
Hello
Java
I solved the above problem by using this code
public class Reader
{
public static void main(String[]args) throws IOException{
try (FileReader in = new FileReader("D:/test.txt")) {
int line = in.read();
while(line!=-1)
{
System.out.print((char)line);
line = in.read();
} }
}
}
But there is one more question if I write for loop instead of while like this
for(int i=0;i<line;i++)
It prints only first line.Could anybody tell me why?
Reader.read() returns int code of single char or -1 if end of the file is reached:
http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html#read()
So, read the file char by char and check LF (Line feed, '\n', 0x0A, 10 in decimal), CR (Carriage return, '\r', 0x0D, 13 in decimal)and end-of-line codes.
Note: Windows OS uses 2 chars to encode the end of line: "\r\n". The most of others including Linux, MacOS, etc. use only "\n" to encode the end of line.
final StringBuilder line = new StringBuilder(); // line buffer
try (FileReader in = new FileReader("D:/test.txt")) {
int chAr, prevChar = 0x0A; // chAr - just read char, prevChar - previously read char
while (prevChar != -1) { // until the last read char is EOF
chAr = in.read(); // read int code of the next char
switch (chAr) {
case 0x0D: // CR - just
break; // skip
case -1: // EOF
if (prevChar == 0x0A) {
break; // no need a new line if EOF goes right after LF
// or no any chars were read before (prevChar isn't
// changed from its initial 0x0A)
}
case 0x0A: // or LF
System.out.println("line:" + line.toString()); // get string from the line buffer
line.setLength(0); // cleanup the line buffer
break;
default: // if any other char code is read
line.append((char) chAr); // append to the line buffer
}
prevChar = chAr; // remember the current char as previous one for the next iteration
}
}

Java / Javascript : File Comparison line by line while ignoring certain section

QUESTION :
Is there a better way to compare two low size(100Kb) files, while selectively ignoring a certain portion of text. and report differences
Looking for default/existing java libraries or any windows native apps
Below is scenario:
Expected file 1 located at D:\expected\FileA_61613.txt
..Actual file 2 located at D:\actuals\FileA_61613.txt
Content in expected File
Some first line here
There may be whitespaces, line breaks, indentation and here is another line
Key : SomeValue
Date : 01/02/2012
Time : 18:20
key2 : Value2
key3 : Value3
key4 : Value4
key5 : Value5
Some other text again to indicate that his is end of this file.
Actual File to be compared:
Some first line here
There may be whitespaces, line breaks, indentation and here is another line
Key : SomeValue
Date : 18/09/2013
Timestamp : 15:10.345+10.00
key2 : Value2
key3 : Value3
key4 : Something Different
key5 : Value5
Some other text again to indicate that his is end of this file.
File 1 and 2 need to be compared line by line., WITHOUT ignoring
whitespaces, indentation, linebreaks
The comparison result should be like something below:
Line 8 - Expected Time, but actual Timestamp
Line 8 - Expected HH.mm, but actual HH.mm .345+10.00
Line 10 - Expected Value4, but actual Something different.
Line 11 - Expected indentation N spaces, but actual only X spaces
Line 13 - Expected a line break, but no linebreak present.
Below have also changed but SHOULD BE IGNORED :
Line 7 - Expected 01/02/2012, but actual 18/09/2013 (exactly and only the 10chars)
Line 8 - Expected 18:20 but actual :15:20 (exactly and only 5 chars should be ignored)
Note : The remaining .345+10.00 should be reported
It is fine even if result just contains the line numbers and no analysis of why it failed.
But it should not just report a failure at line 8 and exit.
It should report all the changes, except for the excluded "date" and "time" values.
Some search results pointed to solutions using Perl.
But Looking for Java / Javascript solutions.
The inputs to the solution would be full file path to both the files.
My current work-around:
Replace the text to be ignored with '#'.
When performing comparison, if we encounter #, do not consider as difference.
Below is my working code. But I need to know if i can use some default / existing libraries or functions to achieve this.
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class fileComparison {
public static void main(String[] args) throws IOException {
FileInputStream fstream1 = new FileInputStream(
"D:\\expected\\FileA_61613.txt");
FileInputStream fstream2 = new FileInputStream(
"D:\\actuals\\FileA_61613.txt");
DataInputStream in1 = new DataInputStream(fstream1);
BufferedReader br1 = new BufferedReader(new InputStreamReader(in1));
DataInputStream in2 = new DataInputStream(fstream2);
BufferedReader br2 = new BufferedReader(new InputStreamReader(in2));
int lineNumber = 0;
String strLine1 = null;
String strLine2 = null;
StringBuilder sb = new StringBuilder();
System.out.println(sb);
boolean isIgnored = false;
while (((strLine1 = br1.readLine()) != null)
&& ((strLine2 = br2.readLine()) != null)) {
lineNumber++;
if (!strLine1.equals(strLine2)) {
int strLine1Length = strLine1.length();
int strLine2Length = strLine2.length();
int maxIndex = Math.min(strLine1Length, strLine2Length);
if (maxIndex == 0) {
sb.append("Mismatch at line " + lineNumber
+ " all characters " + '\n');
break;
}
int i;
for (i = 0; i < maxIndex; i++) {
if (strLine1.charAt(i) == '#') {
isIgnored = true;
continue;
}
if (strLine1.charAt(i) != strLine2.charAt(i)) {
isIgnored = false;
break;
}
}
if (isIgnored) {
sb.append("Ignored line " + lineNumber + '\n');
} else {
sb.append("Mismatch at line " + lineNumber + " at char "
+ i + '\n');
}
}
}
System.out.println(sb.toString());
br1.close();
br2.close();
}
}
I am able to get the output as :
Ignored line 7
Mismatch at line 8 at char 4
Mismatch at line 11 at char 13
Mismatch at line 12 at char 8
Mismatch at line 14 all characters
However, when there are multiple differences in same line. I am not able to log them all, because i am comparing char by char and not word by word.
I did not prefer word by word comparison because, i thought it would not be possible to compare linebreaks, and whitespaces. Is my understanding right ?
java.lang.StringIndexOutOfBoundsException comes from this code:
for (int i = 0; i < strLine1.length(); i++) {
if (strLine1.charAt(i) != strLine2.charAt(i)) {
System.out.println("char not same at " + i);
}
}
When you scroll larger String strLine to an index, that is greater than the length of strLine2 (second file is smaller than the first) you get that exception. It comes, because strLine2 does not have values on those indexes when it is shorter.

Java find and replace text

Hi i'm working on an android app and this is my problem
I have a text file that is maybe 100 lines long it differs from phone to phone but lets say a section is like this
line 1 = 34
line 2 = 94
line 3 = 65
line 4 = 82
line 5 = 29
etc
each line will be equal to some number however that number will be different from phone since my application will be changing this number and it may already be different before my app is installed. So here's my problem i want to search the text file for say "line 3 = " then delete that entire line and replace it with "line 3 = some number"
My main goal is to change that number at the end of line 3 and keep line 3 that is the text exactly the same i only want to edit the number however the problem is that number will always be different
How can i go about doing this? thanks for any help
You can't "insert" or "remove" characters in the middle of a file. I.e., you can't replace 123 with 1234 or 12 in the middle of a file.
So either you "pad" each number so they all have equal width, i.e., you represent 43 as for instance 000043, or you'll probably have to regenerate the whole file.
To regenerate the whole file, I suggest you read the original file line by line, process the lines as appropriate, and write them out to a new, temporary file along the way. Then, when you're through, you replace the old file with the new one.
To process the line I suggest you do something like
String line = "line 3 = 65";
Pattern p = Pattern.compile("line (\\d+) = (\\d+)");
Matcher m = p.matcher(line);
int key, val;
if (m.matches()) {
key = Integer.parseInt(m.group(1));
val = Integer.parseInt(m.group(2));
// Update value if relevant key has been found.
if (key == 3)
val = 123456;
line = String.format("line %d = %d", key, val);
}
// write out line to file...
Thanks guys for the replies but what i ended up doing was using the sed command in bash and the wild card command * to replace the line and then just ran the script through java which went a little like this
Script
busybox sed -i 's/line 3 = .*/line 3 = 70/g' /path/to/file
Java
Command
execCommand("/path/to/script");
Method
public Boolean execCommand(String command)
{
try {
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (IOException e) {
return false;
} catch (InterruptedException e) {
return false;
}
return true;
}
The simplest solution is to read the whole file into memory and then replace the line want to change and then write it back to the file.
For exmple:
String input = "line 1 = 34\nline 2 = 94\nline 3 = 65\nline 4 = 82\nline 5 = 29\n";
String out = input.replaceAll("line 3 = (\\d+)", "line 3 = some number");
...outputs:
line 1 = 34
line 2 = 94
line 3 = some number
line 4 = 82
line 5 = 29
A couple thoughts. An easier way to do this (if possible) would be to store these lines in a collection (like an ArrayList) and do all of your manipulation within your collection.
Another solution can be found here. If you need to replace the contents within a text file, you could call a method periodically to do this:
try {
BufferedReader in = new BufferedReader(new FileReader("in.txt"));
PrintWriter out = new PrintWriter(new File("out.txt"));
String line; //a line in the file
String params[]; //holds the line number and value
while ((line = in.readLine()) != null) {
params = line.split("="); //split the line
if (params[0].equalsIgnoreCase("line 3") && Integer.parseInt(params[1]) == 65) { //find the line we want to replace
out.println(params[0] + " = " + "3"); //output the new line
} else {
out.println(line); //if it's not the line, just output it as-is
}
}
in.close();
out.flush();
out.close();
}catch(Exception e) {
e.printStackTrace();
}

Categories