I am trying to read 2 input files containing integers(even duplicates are considered) and trying to find common integers and write them to the output file.
input1.txt
01
21
14
27
31
20
31
input2.txt
14
21
27
08
09
14
Following is the code I tried:
public static void main(String[] args) throws NumberFormatException {
try {
BufferedReader inputFile1 = new BufferedReader(new FileReader(new File("src/input1.txt")));
BufferedReader inputFile2 = new BufferedReader(new FileReader(new File("src/input2.txt")));
FileWriter fileCommon = new FileWriter("src/common.txt");
String lineInput1;
String lineInput2;
int inputArray1[] = new int[10];
int inputArray2[] = new int[10];
int index = 0;
while ((lineInput1 = inputFile1.readLine()) != null) {
inputArray1[index] = Integer.parseInt(lineInput1);
index++;
}
index = 0;
while((lineInput2 = inputFile2.readLine()) != null) {
inputArray2[index] = Integer.parseInt(lineInput2);
index++;
}
for (int a = 0; a < inputArray1.length; a++) {
for (int b = 0;b < inputArray2.length; b++) {
if(inputArray1[a] == inputArray2[b]) {
fileCommon.write(inputArray1[a]);
}
}
}
inputFile1.close();
inputFile2.close();
fileCommon.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I don't understand where I am making mistake. I am not getting any errors and the output file that is generated is empty.
output expected are common integers in both files
14
21
27
Remember, that FileWriter's write(int c) accepts an integer representing a character code from either a specified charset or the platform's default charset, which is mostly extensions of ASCII (for example, in Windows, default charset is Windows-1252 which is an extension of ASCII).
which means, that you actually don't have any (semantical or syntactical) problem per se, and you're writing into file successfully, but! you're writing some special characters which you can't see afterwards.
If you'll invoke write(..) with some integer representing Latin character (or symbol) in the ASCII table, you'll see that it'll write actual English letter (or symbol) into your file.
For instance:
fileCommon.write(37); //will write `%` into your file.
fileCommon.write(66); //will write `B` into your file.
In your code, you're only writing 21, 14 and 27 into your file, and as you can see from the ASCII table:
Decimal 21 represents Negative Acknowledgment
Decimal 14 represents Shift-out
Decimal 27 represents Escape
FileWriter.write(int) will write a single character, in your case 14, 21, and 27 are all control characters that would not be visible in a text file.
common.write("" + arr1[a]);
Should write the string representation. You'll find some other problems though, such as missing line endings and repeated values, but this should get you started.
Here's the thing.
The write(int c) method of FileWriter is not actually write an int value, but write an ASCII code of a single character.For example, write(53) will write a "5" to a file.
In your code, you are acctually writting some symbols.You can use write(String str) method of FileWriter or just use BufferedWriter class to achieve you goal.
The result of the write value is acctually "21141427" by your code, so you have to remove the repeat value when write it and line feed after write each value.
Sorry for the poor English.
You can read Strings from the original input files, instead of ints, and use the String.equals(Object):boolean function to compare Strings.
Then you won't need to parse from String to int, and convert an int to string back when writing to the file.
Also note that writing an int will write the unicode char value to the file, not the number as a string.
The problem is the common.write line. It should be as follows.
common.write(String.valueOf(arr1[a])+"\n");
Additionally, This would perform much better if you put all of the data from the first file into a Map vs an array then when reading the second file just check the map for the key and if it exists write to common.
If you are dead set on using an array you can sort the first array and use a binary search. This would also perform much better than looping through everything over and over.
Related
I am supposed to write a program using command line arguments to put in 3 different files, a human DNA sequence, a mouse DNA sequence, and an unknown sequence. Without using arrays, I have to compare each character and give the percent match as well aas which one it closely matches up to. Here is what I have so far
import java.io.File;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.*;
public class Lucas_Tilak_Hw8_DNA
{
public static void main (String args[]) throws IOException
{
//First let's take in each file
File MouseFile = new File(args[0]);
File HumanFile = new File(args[1]);
File UnknownFile = new File(args[2]);
//This allows us to view individual characters
FileInputStream m = new FileInputStream(MouseFile);
FileInputStream h = new FileInputStream(HumanFile);
FileInputStream u = new FileInputStream(UnknownFile);
//This allows us to read each character one by one.
DataInputStream mouse = new DataInputStream(m);
DataInputStream human = new DataInputStream(h);
DataInputStream unk = new DataInputStream(u);
//We initialize our future numerators
int humRight = 0;
int mouRight = 0;
//Now we set the counting variable
int countChar = 0;
for( countChar = 0; countChar < UnknownFile.length(); countChar++);
{
//initialize
char unkChar = unk.readChar();
char mouChar = mouse.readChar();
char humChar = human.readChar();
//add to numerator if they match
if (unkChar == humChar)
{
humRight++;
}
if (unkChar == mouChar)
{
mouRight++;
}
//add to denominator
countChar++;
}
//convert to fraction
long mouPercent = (mouRight/countChar);
long humPercent = (humRight/countChar);
//print fractions
System.out.println("Mouse Compare: " + mouPercent);
System.out.println("Human Compare: " + humPercent);
if (mouPercent > humPercent)
{
System.out.println("mouse");
}
else if (mouPercent < humPercent)
{
System.out.println("human");
}
else
{
System.out.println("identity cannot be determined");
}
}
}
If I put in random code {G, T, C, A} for each file I use, it doesn't seem to compare characters, so I get O = mouPercent and 0 = humPercent. Please Help!
Several errors in your code are to blame.
Remove the ; from the end of your for() statement. Basically, you are only reading a single character from each file, and your comparison is strictly limited to that first set of characters. It's unlikely they will have any overlap.
Second error: don't use the "file length". Characters are typically encoded as more than one byte, so you're going to get inconsistent results this way. Better to query the stream to see if there are more bytes available, and stopping when you run out of bytes to read. Most Streams or Readers have an available or ready method that will let you determine if there is more to be read or not.
Third error: DataInputStream is not going to do what you expect it to do. Read the docs -- you're getting strange characters because it's always pulling 2 bytes and building a character using a modified UTF-8 scheme, which only really maps to characters written by the corresponding DataOutput implementing classes. You should research and modify your code to use BufferedReader instead, which will more naturally respect other character encodings like UTF-8, etc. which is most likely the encoding of the files you are reading in.
TL;DR? Your loop is broken, file length is a bad idea for loop terminating condition, and DataInputStream is a special unicorn, so use BufferedReader instead when dealing with characters in normal files.
Try using floats instead of longs for your percentage variables.
My .java file consists of a series of codes and each line is of variable size.
The .java file is shown below:
public class MyC{
public void MyMethod()
{
System.out.println("My method has been accessed");
System.out.println("hi");
String l;
int x=0;
}
}
Briefly, what i want to do is to scan the .java file for errors and capture the errors in a string.
I have used a diagnostic collector to capture the start and end positions of the error.
Suppose I've made an error at line 7: in x=0;
The diagnostic collector will return me the positions for example 143-145 error has occurred.
I also get the line numbers but the positions returned are relative to the whole .java file. Thus using the line numbers would be pointless as each line is of variable length and the positions are relative to the whole file. It will be difficult to compute the actual position of the error at a line.
And there is no way for me to get the end position of the last character in the previous line if there is no error at the last character of the previous line(e.g: error at line 7: previous line = line 6).
Is there a way for me to get a string by using its position(start and end) from a java file?
The easiest way is to use a RandomAccessFile.
It has a method called seek, which takes the position it should seek to:
String getStringFromFile(String fileName, long position, int length) throws IOException {
byte[] buffer = new byte[length]; // You may want to take care of multi-byte encodings here
RandomAccessFile file = new RandomAccessFile(fileName, "r");
file.seek(position);
file.readFully(buffer);
return new String(buffer); // You may want to add encoding handling here
}
Edit: You can also use a loop and read a single char at a time and use a char array instead of a byte array. It would probably be simpler for you. Use the readChar method instead of read.
Switched read to readFully to guarantee that all bytes are read.
Im trying to output an integer array to a file and have hit a snag. The code executes properly, no errors thrown, but instead of giving me a file containing the numbers 1-30 it gives me a file filled with [] [] [] [] [] I have isolated the problem to the included code segment.
try
{
BufferedWriter bw = new BufferedWriter(new FileWriter(filepath));
int test=0;
int count=0;
while(count<temps.length)
{
test=temps[count];
bw.write(test);
bw.newLine();
bw.flush();
count++;
}
}
catch(IOException e)
{
System.out.println("IOException: "+e);
}
filepath refers to the location of the output file. temps is an array containing the values 1-30. If anymore information is necessary, i will be happy to provide.
BufferedWriter.write(int) writes the character value of the int, not the int value. So outputing 65 should put the letter A to file, 66 would print B...etc. You need to write the String value not the int value to the stream.
Use BufferedWriter.write(java.lang.String) instead
bw.write(String.valueOf(test));
I suggest to use PrintStream or PrintWriter instead:
PrintStream ps = new PrintStream(filePath, true); // true for auto-flush
int test = 0;
int count = 0;
while(count < temps.length)
{
test = temps[count];
ps.println(test);
count++;
}
ps.close();
The problem you are having is that you are using the BufferedWriter.write(int) method. What is confusing you is that while the method signature indicates it's writing an int, it's actually expecting that int to represent an encoded character. In other words, writing 0 is writing NUL, and writing 65 would output 'A'.
From Writer's javadoc:
public void write(int c) throws IOException
Writes a single character. The character to be written is contained in the 16 low-order bits of the given integer value; the 16 high-order bits are ignored.
A simple way to correct your problem is to convert the number to a String before writing. There are numerous ways to achieve this, including:
int test = 42;
bw.write(test+"");
You could convert the integer array to a byte array and do something like this:
public void saveBytes(byte[] bytes) throws FileNotFoundException, IOException {
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filepath))) {
out.write(bytes);
}
}
You write the number as an Integer to the file, but you want it to be a string.
change bw.write(test); to bw.write(Integer.toString(test));
import java.io.*;
class BS{
public void pStr(){
try{
String command="cat /usr/share/doc/bash/rbash.pdf";
Process ps=Runtime.getRuntime().exec(command);
InputStream in = ps.getInputStream();
int c;
while((c=in.read())!=-1){
System.out.print((char)c);
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String args[]){
new BS().pStr();
}
}
jabira-whosechild-lm.local 23:54:00 % java BS|wc
384 2003 43885
jabira-whosechild-lm.local 23:54:05 % wc /usr/share/doc/bash/rbash.pdf
384 2153 43885 /usr/share/doc/bash/rbash.pdf
Why do i see the difference in the number of characters that are read
and printed to the console
The method InputStream.read() reads only one byte.
Your source code line System.out.print((char)c); is wrong. The method PrintStream.print(char c) is called and this method writes two bytes for some non-ASCII character values.
You need to call a method that always writes one byte value. The correct method is System.out.write(c);.
Isn't it that the number of characters is the same, but the number of words are different?
I'm guessing that somewhere in your c=in.read() and print((char)c) code there is some encoding issues going on.
Can you save the output to another PDF file and do a binary compare of them? If they are identical then that's really weird! If they're not, then you might find a clue in the differences.
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("rates.txt")));
for (int i=0; i<9; i++){
while(s.hasNext()){rates[i] = s.next();}
System.out.println(rates[i]);
}
}catch (IOException e){
System.out.println(e);
}
finally {
if (s != null) {
s.close();
}
}
When I run this code, it reads the last chunk of characters in my txt file, places them in rates[0], sticks null in 1-9. I'm not sure why it's reading the end of my file first. The contents of the txt are below..
USD 1.34
EUR 1.00
JPY 126.28
GBP 0.88
INR 60.20
It reads the 60.20, which is all it is recording in the array. Any help would be appreciated. I guess I could give you the results of running this code:
run:
60.20
null
null
null
null
null
null
null
null
BUILD SUCCESSFUL (total time: 0 seconds)
while(s.hasNext()){rates[i] = s.next();}
In plain english, this says: While there are tokens left, put the next token into rates[i].
So it will put the first token into rates[i], then the next token into rates[i], then the next token into rates[i], ..., and finally the last token into rates[i]. Since i is not modified, all the values are written into the same element of the array, overwriting the previously read values.
I recommend:
Using List instead of array
More flexible, much easier to work with, takes advantage of Java Collections Framework, etc
Not storing the currency symbol and the numeric exchange rate all in one mixed bag
...but using a class to encapsulate the pair
Using Scanner.nextDouble() to read the numeric exchange rate (which presumably you'll want to convert to double anyway)
So, something like this:
List<ExchangeRate> allRates = new ArrayList<ExchangeRate>();
while (sc.hasNext()) {
String symbol = sc.next();
double rate = sc.nextDouble();
allRates.add(new ExchangeRate(symbol, rate));
}
Note how:
You no longer need to know how many elements to allocate in an array
The symbol and the rate aren't all thrown into one mixed bag
List.add means no counter that you need to keep track of and manage
i.e. the bug in your original question!
I think the problem is that line 5, which contains your while loop, reads the entire file input. So you read your entire file on the first for loop iteration where i = 0; The next time your for loop there is nothing left to read.
You probably want something like this instead:
List rates = new ArrayList();
while (s.hasNext()) {
rates.add(s.next());
}
One other potential problem: FileReader uses the platform default encoding. This can be appropriate to process user-supplied files, but if the files are part of the application, they can get corrupted when the application is run on a system with an incompatible default encoding (and no, using only ASCII characters does not protect you completely against this).
To avoid the problem, use new InputStreamReader(new FileInputStream(filename), encoding) instead - and realize that you actually have to pick an encoding for your file.