Copying binary file changes newline character to window's standard..? Java - java

For some reason, this code is changing any '\n' characters from the input and replacing it with '\n\r' in the new outputed file.
I reference a couple websites, and still haven't figured it out.. Anyone have an idea?
Thanks a lot!
Socket connectionSocket = sData.accept();
InputStream inputStream = connectionSocket.getInputStream();
BufferedInputStream inputBufferedStream = new BufferedInputStream(inputStream);
FileOutputStream outputStream = new FileOutputStream("/home/greg/1");
byte[] buffer = new byte[1024];
long count = 0;
int n = 0;
while ((n = inputBufferedStream.read(buffer))>=0) {
outputStream.write(buffer, 0, n);
count += n;
}
outputStream.close();
}

The particular code isn't doing that. Likely those \r\n were simply already in the input source.
It can only happen when you're reading it using for example BufferedReader#readLine() which eats the newlines and writing it using PrintWriter#println() which appends the platform default newlines. Probably the other side is doing that? After all, a Reader/Writer shouldn't be used for binary data. It may malform it. Use InputStream/OutputStream for it.

Related

Copy content from one file to multiple file using java

FileInputStream Fread = new FileInputStream("somefilename");
FileOutputStream Fwrite = null;
for (int i = 1; i <= 5; i++)
{
String fileName = "file" + i + ".txt";
Fwrite = new FileOutputStream(fileName);
int c;
while ((c = Fread.read()) != -1)
{
Fwrite.write((char) c);
}
Fwrite.close();
}
Fread.close();
The above code writes only to one file. How to make it work to write the content of one file to multiple files?
FYI: Note that the read() method you used returns a byte, not a char, so calling write((char) c) should have been just write(c).
To write to multiple files in parallel when copying a file, you create a array of output streams for the destination files, then iterate the array to write the data to all of them.
For better performance, you should always do this using a buffer. Writing one byte at a time will not perform well.
public static void copyToMultipleFiles(String inFile, String... outFiles) throws IOException {
OutputStream[] outStreams = new OutputStream[outFiles.length];
try {
for (int i = 0; i < outFiles.length; i++)
outStreams[i] = new FileOutputStream(outFiles[i]);
try (InputStream inStream = new FileInputStream(inFile)) {
byte[] buf = new byte[16384];
for (int len; (len = inStream.read(buf)) > 0; )
for (OutputStream outStream : outStreams)
outStream.write(buf, 0, len);
}
} finally {
for (OutputStream outStream : outStreams)
if (outStream != null)
outStream.close();
}
}
You will have to create multiple instances of FileOutputStream fwrite1, fwrite2, fwrite3, one per each file you want to write to, then, as you read, you simply write to all of them. This is how you achieve it.
Add this line:
Fread.reset();
after Fwrite.close();
And change the first line of code to this:
InputStream Fread = new BufferedInputStream(new FileInputStream("somefilename"));
Fread.mark(0);
The FReadstream gets to the end once and then there is nothing to make it start from the beginning.
To solve this you can:
call to FRead.reset() after each file writing
cache FRead's value somewhere and write to FWrite from this source
create an array / collection of FileOutputStream and write each byte to all of them during iteration
The recommended solution is of course the first one.
Also there are some problems in your code:
You are highly encouraged to use try-with-resouce for Streams as they should be safely closed
You seem to not follow naming conventions which say to name variables in lowerCamelCase

Convert InputStreamReader to InputStream

How can I convert InputStreamReader to InputStream? I have an InputStream which contains some string and byte data and I want to parse it. So I wrap my InputStream to BufferedReader. Then I read 3 lines from it. After that I want to get the rest of data(bytes) as is. But if I try to get it nothing happens.
Code snippet:
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String endOfData = br.readLine();
String contentDisposition = br.readLine();
String contentType = br.readLine();
file = new File(filename);
if(file.exists()) file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] data = new byte[8192];
int len = 0;
while (-1 != (len = is.read(data)) )
{
fos.write(data, 0, len);
Log.e("len", len+"");
}
fos.flush();
fos.close();
is.close();
The file is empty. If I don't wrap InputStream it works fine, but I need to read 3 lines and remove it.
Thanks.
If you want to mix text and byte data together, you should use OutputStream.writeUTF to write out those 3 lines, this way one single InputStream will be able to retrieve all the data that you need.
Take a look at commons-io's ReaderInputStream: it is a little heavy handed, but you can wrap the BufferedReader with that and read it as an input stream again.
It's pretty hard to mix byte and character input correctly, especially once you start throwing buffered readers / streams into the mix. I'd suggest that you either pick one and stick with it (converting your bytes to strings as necessary; care with the encoding!) or wrap the entire thing in a ZipOutputStream so you can have multiple logical "files" with different contents.

Convert DataInput to DataInputStream?

How can I convert DataInput to DataInputStream in java?
I need to know the size of the DataInput.
Since a stream, by definition, really has no begining or end and thus no fool proof way of knowing how much is available, you just have to read from the stream in fixed sized chunks. It almost sounds like you'd be better off with plain old .read() rather than readFully():
DataInputStream dis = new DataInputStream(...);
byte[] buf = new byte[1024];
int lastRead = 0;
do {
lastRead = dis.read(buf);
//do something with 'buf' here
} while (lastRead > 0);
You'll encounter difficulty when you want know how many bytes to be read. Simplest solution is to cast it to a ByteArrayInputStream and use it's available() method to get to know how many bytes are available for reading.
Following example worked for me
DataInput in = (...);
ByteArrayInputStream bis = (ByteArrayInputStream) in;
byte[] buffer = new byte[bis.available()];
in.readFully(buffer);
//use buffer as your wish

Java InputStream reading problem

I have a Java class, where I'm reading data in via an InputStream
byte[] b = null;
try {
b = new byte[in.available()];
in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
It works perfectly when I run my app from the IDE (Eclipse).
But when I export my project and it's packed in a JAR, the read command doesn't read all the data. How could I fix it?
This problem mostly occurs when the InputStream is a File (~10kb).
Thanks!
Usually I prefer using a fixed size buffer when reading from input stream. As evilone pointed out, using available() as buffer size might not be a good idea because, say, if you are reading a remote resource, then you might not know the available bytes in advance. You can read the javadoc of InputStream to get more insight.
Here is the code snippet I usually use for reading input stream:
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = in.read(buffer)) >= 0){
for (int i = 0; i < bytesRead; i++){
//Do whatever you need with the bytes here
}
}
The version of read() I'm using here will fill the given buffer as much as possible and
return number of bytes actually read. This means there is chance that your buffer may contain trailing garbage data, so it is very important to use bytes only up to bytesRead.
Note the line (bytesRead = in.read(buffer)) >= 0, there is nothing in the InputStream spec saying that read() cannot read 0 bytes. You may need to handle the case when read() reads 0 bytes as special case depending on your case. For local file I never experienced such case; however, when reading remote resources, I actually seen read() reads 0 bytes constantly resulting the above code into an infinite loop. I solved the infinite loop problem by counting the number of times I read 0 bytes, when the counter exceed a threshold I will throw exception. You may not encounter this problem, but just keep this in mind :)
I probably will stay away from creating new byte array for each read for performance reasons.
read() will return -1 when the InputStream is depleted. There is also a version of read which takes an array, this allows you to do chunked reads. It returns the number of bytes actually read or -1 when at the end of the InputStream. Combine this with a dynamic buffer such as ByteArrayOutputStream to get the following:
InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
while ( -1 != ( read = in.read( input ) ) ) {
buffer.write( input, 0, read );
}
input = buffer.toByteArray()
This cuts down a lot on the number of methods you have to invoke and allows the ByteArrayOutputStream to grow its internal buffer faster.
File file = new File("/path/to/file");
try {
InputStream is = new FileInputStream(file);
byte[] bytes = IOUtils.toByteArray(is);
System.out.println("Byte array size: " + bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
Below is a snippet of code that downloads a file (*. Png, *. Jpeg, *. Gif, ...) and write it in BufferedOutputStream that represents the HttpServletResponse.
BufferedInputStream inputStream = bo.getBufferedInputStream(imageFile);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int bytesRead = 0;
byte[] input = new byte[DefaultBufferSizeIndicator.getDefaultBufferSize()];
while (-1 != (bytesRead = inputStream.read(input))) {
buffer.write(input, 0, bytesRead);
}
input = buffer.toByteArray();
response.reset();
response.setBufferSize(DefaultBufferSizeIndicator.getDefaultBufferSize());
response.setContentType(mimeType);
// Here's the secret. Content-Length should equal the number of bytes read.
response.setHeader("Content-Length", String.valueOf(buffer.size()));
response.setHeader("Content-Disposition", "inline; filename=\"" + imageFile.getName() + "\"");
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream(), DefaultBufferSizeIndicator.getDefaultBufferSize());
try {
outputStream.write(input, 0, buffer.size());
} finally {
ImageBO.close(outputStream);
}
} finally {
ImageBO.close(inputStream);
}
Hope this helps.

Why does my Sax Parser produce no results after using InputStream Read?

I have this piece of code which I'm hoping will be able to tell me how much data I have downloaded (and soon put it in a progress bar), and then parse the results through my Sax Parser. If I comment out basically everything above the //xr.parse(new InputSource(request.getInputStream())); line and swap the xr.parse's over, it works fine. But at the moment, my Sax parser tells me I have nothing. Is it something to do with is.read (buffer) section?
Also, just as a note, request is a HttpURLConnection with various signatures.
/*Input stream to read from our connection*/
InputStream is = request.getInputStream();
/*we make a 2 Kb buffer to accelerate the download, instead of reading the file a byte at once*/
byte [ ] buffer = new byte [ 2048 ] ;
/*How many bytes do we have already downloaded*/
int totBytes,bytes,sumBytes = 0;
totBytes = request.getContentLength () ;
while ( true ) {
/*How many bytes we got*/
bytes = is.read (buffer);
/*If no more byte, we're done with the download*/
if ( bytes <= 0 ) break;
sumBytes+= bytes;
Log.v("XML", sumBytes + " of " + totBytes + " " + ( ( float ) sumBytes/ ( float ) totBytes ) *100 + "% done" );
}
/* Parse the xml-data from our URL. */
// OLD, and works if comment all the above
//xr.parse(new InputSource(request.getInputStream()));
xr.parse(new InputSource(is))
/* Parsing has finished. */;
Can anyone help me at all??
Kind regards,
Andy
'I could only find a way to do that
with bytes, unless you know another
method?'.
But you haven't found a method. You've just written code that doesn't work. And you don't want to save the input to a String either. You want to count the bytes while you're parsing them. Otherwise you're just adding latency, i.e. wasting time and slowing everything down. For an example of how to do it right, see javax.swing.ProgressMonitorInputStream. You don't have to use that but you certainly do have to use a FilterInputStream of some sort, probaby one you write yourself, that is wrapped around the request input stream and passed to the parser.
Your while loop is consuming the input stream and leaving nothing for the parser to read.
For what you're trying to do, you might want to look into implementing a FilterInputStream subclass wrapping the input stream.
You are building an InputStream over another InputStream that consumes its data before.
If you want to avoid reading just single bytes you could use a BufferedInputStream or different things like a BufferedReader.
In any case it's better to obtain the whole content before parsing it! Unless you need to dynamically parse it.
If you really want to keep it on like you are doing you should create two piped streams:
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream();
pipeIn.connect(pipeOut);
pipeOut.write(yourBytes);
xr.parse(pipeIn);
Streams in Java, like their name suggest you, doesn't have a precise dimension neither you know when they'll finish so whenever you create an InputStream, if you read from them you cannot then pass the same InputStream to another object because data is already being consumed from the former one.
If you want to do both things (downloading and parsing) together you have to hook between the data received from the HTTPUrlConncection you should:
first know the length of the data being downloaded, this can be obtained from HttpUrlConnection header
using a custom InputStream that decorates (this is how streams work in Java, see here) updading the progressbar..
Something like:
class MyInputStream extends InputStream
{
MyInputStream(InputStream is, int total)
{
this.total = total;
}
public int read()
{
stepProgress(1);
return super.read();
}
public int read(byte[] b)
{
int l = super.read(b);
stepProgress(l);
return l;
}
public int read(byte[] b, int off, int len)
{
int l = super.read(b, off, len);
stepProgress(l);
return l
}
}
InputStream mis= new MyInputStream(request.getInputStream(), length);
..
xr.parse(mis);
You can save your data in a file, and then read them out.
InputStream is = request.getInputStream();
if(is!=null){
File file = new File(path, "someFile.txt");
FileOutputStream os = new FileOutputStream(file);
buffer = new byte[2048];
bufferLength = 0;
while ((bufferLength = is.read(buffer)) > 0)
os.write(buffer, 0, bufferLength);
os.flush();
os.close();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
FileInputStream fis = new FileInputStream(file);
xpp.setInput(new InputStreamReader(fis));
}

Categories