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));
Related
I understand the issue, but I'm not sure how to resolve it.
public static List<String> getNumbersInRange(long start, long end) {
for (long i = start; i < end; i++) {
String padded = String.format("%012d", i);
result.add(padded);
}
return result;
}
Above is the number generator, and below is the file generator. How can I do this so that I don't get a memory leak?
long value = 1L;
long value1 = 100000000001L;
getNumbersInRange(value,value1);
BufferedWriter writer = new BufferedWriter(new FileWriter("UPC.txt"));
for(String str: result) {
writer.write(str + System.lineSeparator());
}
writer.close();
Forgive me if this isn't well thought out, I haven't done any programming in awhile.
You won't be able to hold 100_000_000_000 long numbers in the list because the size of any collection/array in Java is integer, thus it cannot contain more than Integer.MAX_VALUE items.
In order to print the mentioned range into a file, it would take 1,088,888,888,890 digits in plain number format plus 100,000,000,000 delimiters to separate the numbers thus it would take over 1,107 GB of the disk space. Assuming that your HDD is able to write at speed 100 MB/s, it would take over 3 hours to write this file.
Instead of having a function which returns the list of strings you want to print, you should write a function which prints the strings to the file as you generate them. This way you do not have to store a giant list in memory.
You could try something like this:
long value = 1L;
long value1 = 100000000001L;
LongStream.rangeClosed(value, value1)
.forEach(val -> {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("UPC.txt", true));){
writer.write(String.format("%012d", val) + System.lineSeparator());
} catch (IOException e) {
e.printStackTrace();
}
});
This way,
You dont save in-memory data
Data is autogenerated for you
FileWriter constructor should have second parameter as true to indicate you want to append to the file
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.
I am using Readfully in java to read a file. The below code illustrates it.
import java.io.*;
public class RandomAccessFileDemo {
public static void main(String[] args) {
try {
// create a string and a byte array
// create a new RandomAccessFile with filename test
RandomAccessFile raf = new RandomAccessFile("/home/mayank/Desktop/Image/Any.txt", "rw");
// set the file pointer at 0 position
raf.seek(0);
int Length = (int)raf.length();
// create an array equal to the length of raf
byte[] arr = new byte[Length];
// read the file
raf.readFully(arr,0,Length);
// create a new string based on arr
String s2 = new String(arr);
// print it
System.out.println("" + s2);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
The contents of Any.txt is Hello World!!
The above code prints Hello World!!
but when I change
raf.readFully(arr,0,Length);
to
raf.readFully(arr,3,Length-3);
Instead of getting the output lo World!!, I get no error.
Can any one explain me how to use readfully.
Or how to get the output lo World!!?
readFully will start reading from the current position in the file by default. To skip the first three characters, use:
raf.skipBytes(3);
before using readFully. Also there's no reason to use an offset, so use:
raf.readFully(arr,0,Length - 3);
and things will be peachy.
IMPORTANT NOTE: This assumes that the first 3 characters are only one byte a piece, which isn't necessarily the case with some character sets. But since this is likely a beginning homework assignment or tutorial, this is likely the answer you're looking for.
Per the javadoc, the off and len parameters of readFully(byte[] b, int off, int len) affect where in your byte array the raf data is placed, not how much of the raf data is read. In all cases the remainder of the file is read fully.
If b is null, a NullPointerException is thrown. If off is negative, or
len is negative, or off+len is greater than the length of the array b,
then an IndexOutOfBoundsException is thrown. If len is zero, then no
bytes are read. Otherwise, the first byte read is stored into element
b[off], the next one into b[off+1], and so on. The number of bytes
read is, at most, equal to len.
try this instead:
raf.skipBytes(3);
raf.readFully(arr,3,Length-3);
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.
This is my first post on here, so apologies for the problems it likely has.
I've been working with a custom input stream recently, that uses a byte array to store data in (similar to a ByteArrayInputStream) but with more control over the pointer. The problem is for some reason my implementation of read() starts returning negative numbers after the values get past 127, which causes DataInputStream to assume it's the EOF.
I've condensed things into a small program to demonstrate the problem:
(broken up into pieces, because I can't seem to figure out how to fit it all into a single code block)
The custom input stream class:
class TestByteArrayInputStream extends InputStream {
byte[] data;
{
// fill with some data
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(out);
try {
for (int i = 0; i < 256; i++) { // fill array with shorts valued 0-255
dout.writeShort(i);
}
} catch (Throwable t) {
t.printStackTrace();
}
data = out.toByteArray();
}
int pointer = 0;
#Override
public int read() throws IOException {
if (pointer >= data.length) {
pointer = 0;
}
return data[pointer++]; // I've tried casting this to a char to remove signing, and using Integer.valueOf, but neither solve the problem.
}
}
And here's the main method:
public class Bugdemo {
public static void main(String[] args) {
TestByteArrayInputStream tin = new TestByteArrayInputStream();
DataInputStream din = new DataInputStream(tin);
try { // read through normally
for (int i = 0; i < 256; i++) {
System.out.println(din.readShort());
}
} catch (Throwable t) {
System.out.println(t.toString()); // avoid logging issues
}
tin.pointer = 0; // reset to beginning of data
try {
for (int i = 0; i < 256; i++) {
// readShort code with added debugging
int ch1 = tin.read();
int ch2 = tin.read();
if ((ch1 | ch2) < 0) {
System.out.print("readshort \"eof\": ");
System.out.printf("data in array is %02X ", tin.data[tin.pointer - 2]);
System.out.printf("%02X ", tin.data[tin.pointer - 1]);
System.out.printf(" but got %02X ", ch1);
System.out.printf("%02X from read()", ch2);
System.out.println();
//throw new EOFException(); // this is in DataInputStream.readShort after if((ch1 | ch2) < 0)
} else {
System.out.println((short) ((ch1 << 8) + (ch2 << 0)));
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
And here's the output (pasted so this isn't too long): http://paste.ubuntu.com/6642589/
(is there a better way of doing this on here?)
The important bit:
readshort "eof": data in array is 00 80 but got 00 FFFFFF80 from read()
From my debugging I'm pretty sure it's a casting issue from the byte in the array to an int for returning in read(), but shouldn't it cast properly naturally? If not, what's the proper way of doing this?
readShort works as expected, read too.
Integer datatypes in Java are signed, including byte. As read returns a byte and you are outputting this value as it is you get the negative representation. You have to convert it to an int with the unsigned value before printing with ch1 & 0xff.
No suprises here. The Max Value for bytes is (2 to power 7) - 1
http://docs.oracle.com/javase/7/docs/api/java/lang/Byte.html#MAX_VALUE
all types in java are signed so byte can hold values between -128 +127. You are putting two bytes by writing short
for (int i = 0; i < 256; i++) { // fill array with shorts valued 0-255
dout.writeShort(i);
but the code reads just one byte:
return data[pointer++];
it should be done this way
DataInputStream din = new DataInputStream(new ByteArrayInputStream(out.toByteArray()));
...
return din.readShort();
It isn't always easy. Just a quick summary for those who are still lost:
simple input stream
The read() of an input stream just returns a value in range [0;255].
However, if no data is available, then it will return a -1.
int value = inputStream.read(); // -1 if no data
If you would just cast this to a byte, then you are creating an overflow and you actually convert the range of [0;255] to a range of [-128;127].
byte signedValue = (byte) value;
data input stream
Now, if you wrap your InputStream in a DataInputStream then additional methods are available, such as the readByte() method. This method will return a value in range [-128;127] because that is the range of the byte type of java. Often you may want to convert it to a positive value.
If there is no data available, then of course a DataInputStream cannot return -1. So instead it will throw an EOFException.
byte value = dataInputStream.readByte(); // throws EOFException
int positiveValue = value & 0xFF;
char character = (char) positiveValue;
PS: The DataInputStream offers some convenient methods that help you to read the values immediately in the correct value range.
int positiveValue = dataInputStream.readUnsignedByte();
int positiveValue = dataInputStream.readUnsignedShort();
socket input stream
But it can be more complex. If your initial input stream is actually a SocketInputStream then no matter which method you use or how you wrap it, you will not receive -1 or EOFException. Instead you will receive a SocketTimeoutException.
socket.setSoTimeout(1000);
int value = socketInputStream.read(); // throws SocketTimeoutException
byte signedValue = (byte) value;
char character = (char) value;
There is just a little shortcoming in that last statement: Very rarely the read() method of a SocketInputStream will not return a SocketTimeoutException in case of a timeout. It can actually return a -1 if the input stream is not correctly bound. In that case the connection is broken, and you need to close everything down and reconnect.