BufferedInputStream.mark(int readlimit)
I read java doc but I don't understand when we use this parameter "readlimit"
in this code, I don't understand what's different between mark(1) or mark(100)
public static void main(String[] args) throws Exception {
String s="123456789ABCDEFGHIJKLMNOPQRSDVWXYZ";
byte byteArray[]=s.getBytes();
ByteArrayInputStream BArrayIS=new ByteArrayInputStream(byteArray);
BufferedInputStream BIS=new BufferedInputStream(BArrayIS);
BIS.mark(1);
System.out.println(BIS.read());
}
It has no effect because BufferedInputStream.mark method effects `` which is used in reset method that you don't use.
Repositions this stream to the position at the time the mark method
Related
The following Java code compiles, but there's an error at runtime:
# javac ByteBufTest.java
# java ByteBufTest
Exception in thread "main" java.lang.UnsupportedOperationException
at java.nio.ByteBuffer.array(ByteBuffer.java:959)
at ByteBufTest.<init>(ByteBufTest.java:12)
at ByteBufTest.main(ByteBufTest.java:33)
#
Why does this happen?
Note:Next, I need to use mDirectBuffer in JNI, so I have to use the ByteBuffer.allocateDirect(TEST_BUFFER_SIZE) function。
ByteBufTest.java:
import java.nio.ByteBuffer;
public class ByteBufTest {
public static final int TEST_BUFFER_SIZE = 128;
private ByteBuffer mDirectBuffer;
public ByteBufTest() {
mDirectBuffer = ByteBuffer.allocateDirect(TEST_BUFFER_SIZE);
byte[] buf = mDirectBuffer.array();
buf[1]=100;
}
public void test() {
printBuffer("nativeInitDirectBuffer",mDirectBuffer.array());
}
private void printBuffer( String tag, byte[] buffer ) {
StringBuffer sBuffer = new StringBuffer();
for( int i=0; i<buffer.length; i++ ) {
sBuffer.append(buffer[i]);
sBuffer.append(" ");
}
//System.out.println(tag+sBuffer);
}
public static void main(String[] args) throws Exception {
ByteBufTest item = new ByteBufTest();
item.test();
}
}
This is the expected behaviour. The Javadoc states
throws UnsupportedOperationException - If this buffer is not backed by an accessible array
You should try another approach or search for another implementation, e.g.
mDirectBuffer = ByteBuffer.wrap(new byte[TEST_BUFFER_SIZE]);
This exception occurs at runtime if the resulting buffer is not backed by an accessible array. You can try allocate() method.
You should call java.nio.ByteBuffer.hasArray() to ensure that java.nio.ByteBuffer.array() will succeed in order to write clean and portable code as stated in the Java API documentation:
If this method returns true then the array and arrayOffset methods may safely be invoked
You can allocate a direct writable NIO byte buffer in your Java source code by calling java.nio.ByteBuffer.allocateDirect(int) as you already do and call java.nio.ByteBuffer.get(byte[]) to store the content of the buffer into an array, this method is supported by Android too. Keep in mind that it's a relative operation that affects the position of the NIO buffer.
Maybe another approach would consist in using the NIO buffer as is without doing any conversion but I'm not sure that it suits your needs.
I'm trying to use EasyMock to test that a method runs a specific number of times but I keep getting an IllegalStateException error and I don't understand why. I'm new to EasyMock and JUnit and not very familiar with how to use them so I'm not sure what I'm doing wrong.
My code is:
FileOutputStream mockWriter;
Numbers mockByte;
#Test
public void testNumbers() throws IOException{
mockWriter = createMock(FileOutputStream.class);
mockByte = new Numbers(mockWriter);
mockByte.initByte();
expect(mockByte.generate()).times(10000);
replay(mockWriter);
}
And these are the methods initByte and generate from my Numbers class:
public void initByte() throws IOException{
File outFile = new File("NumbersOutput.txt");
FileOutputStream f = new FileOutputStream(outFile);
for(int i = 0; i < 10000; i++){
int b = generate();
f.write(b);
}
f.flush();
f.close();
}
public int generate(){
return rand.nextInt(100001);
}
The error you're getting is because nothing's calling anything on your mock.
Contrary to your naming, mockByte doesn't refer to a mock at all, so using it in an expect call like this is not going to help you. You should be expecting calls on mockWriter if anything.
However, it's not clear why you're using a mock for a stream at all, nor what the OutputStream in the Numbers constructor is used for. Your initByte() method doesn't use any state within the object other than rand. Even when that's fixed, it would probably be simplest just to use a ByteArrayOutputStream... make your API talk in terms of OutputStream instead of FileOutputStream, and it'll be much easier to test.
I suspect you should:
Remove the construction of a new FileOutputStream from the initByte method, instead writing to the stream you accept in the Numbers constructor
If your constructor parameter type is FileOutputStream, change it to OutputStream to make it cleaner and easier to test
Create a ByteArrayOutputStream in your test - you don't need mocking at all. You can then get all the bytes that have been written, and check them for whatever you want.
Think carefully about what you expect f.write(b) to do. It's only going to write a single byte, so the top 24 bits of your random number are going to be ignored. At that point, why are you choosing a number in the range [0, 10000] anyway?
Suppose I have a method that take in an InputStream.
This method need to wrap this InputStream with a BufferedInputStream to use its mark and reset functionality. However, the passed in InputStream might still be used by the caller of the method.
public static void foo(InputStream is) throws Exception {
BufferedInputStream bis = new BufferedInputStream(is);
int b = bis.read();
}
public static void main(String[] args) {
try {
InputStream is = new FileInputStream(someFile);
foo(is);
int b = is.read(); // return -1
}catch (Exception e) {
e.printStackTrace();
}
}
My questions is: what exactly happen to the original InputStream when the BufferedInputStream is read (or initialized)?
My assumption is that the original InputStream will also move forward if the BufferedInputStream is read. However, after debugging my code, I have found that the InputStream will return -1 instead when read.
If the original InputStream is not readable after such process, how should I go about achieving my purpose:
InputStream is;
foo(is); // Method only take in generic InputStream object
// Processing of the passed in InputStream object require mark and reset functionality
int b = is.read(); // Return the next byte after the last byte that is read by foo()
EDIT:
I suppose what I'm asking for is quite generic and therefore requires a lot of work. As for what I'm working on, I actually don't need the full mark & reset capability so I have found a small work around. However, I will leave the 2nd part of the question here, so feel free to attempt this problem :).
The default bufferSize of a BufferedInputStream is 8192, so when you're reading from BufferedInputStream, it tries to fill it's buffer. So, if you have to read from your InputStream less bytes, than the bufferSize, then the full content of your InputStream is read to the buffer, therefore you're getting -1 after reading from BufferedInputStream
Have a look at the BufferedInputStream source code: http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html
http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#BufferedInputStream%28java.io.InputStream%29
Looks like the BufferedInputStream uses the InputStream for the actions performed with the data stream. The Buffered class simply implements a buffer array for internal use.
Not sure what you could use instead, apart from perhaps copying the InputStream so that you have a second object to call.
BufferedInputStream will pre-load data from the underlying InputStream in batches, which will trigger respective move of the underlying InputStream position. If the buffer size is enough to consume all data from the underlying stream in one go you may well observe the behavior you describe.
Two things:
Any API that accepts a stream as input parameter is probably going to use that stream, so it is unreasonable for the caller to expect the stream to remain in any kind of usable state. Perhaps it would have been better for the java stream classes to enforce single ownership somehow to make that clearer.
As a special case, BufferedInputStream is going to use the underlying stream that it "wraps" because it achieves (a limited form of) mark and reset by buffering block reads, as others have pointed out.
private static class MybufferedInputStream extends BufferedInputStream {
public MybufferedInputStream(InputStream in) {
super(in);
}
public int getBufferSize(){
int i=0;
for (Byte byte1 : super.buf) {
if (byte1!=0) {
i++;
}
}
return i;
}
}
then you can call the getBufferSize() after read() to see the difference between a small file and a larger file.
Is it possible to have a regexp replace in a printstream?
I have a piece of code that logs all text that is shown in my console windows but it also logs ANSI escape codes.
I have found this regexp "s:\x1B\[[0-9;]*[mK]::g" to remove them but that only works with strings.
Is there a way to apply a regex replace to a constant stream of strings and filter out the ANSI escape codes?
If possible, dumb it down as much as possible, I am still a newbie when it comes to programming, I am just building upon a already program.
EDIT:
I have this code which I found somewhere else on stack overflow, this allows me to stream to a logfile and to the console at the same time.
This is what I use and then I set the out to tee after this.
Logging tee = new Logging(file, System.out);
.
package com.md_5.mc.chat;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class Logging extends PrintStream
{
private final PrintStream second;
public Logging(OutputStream main, PrintStream second)
{
super(main);
this.second = second;
}
public void close()
{
super.close();
}
public void flush()
{
super.flush();
this.second.flush();
}
public void write(byte[] buf, int off, int len)
{
super.write(buf, off, len);
this.second.write(buf, off, len);
}
public void write(int b)
{
super.write(b);
this.second.write(b);
}
public void write(byte[] b) throws IOException
{
super.write(b);
this.second.write(b);
}
}
Create create a subclass of FilterOutputStream, say RegexOutputStream. This class should buffer all data written to it (from the different write(...) methods). In the flush() method, it should apply the regex and then write the result to the underlying OutputStream.
Next, instantiate the PrintWriter to write to the RegexOutputStream. This way you don't need to alter the behaviour of the PrintWriter class. In case you don't want the filtering anymore, you can just take the RegexOutStream out of the chain, and everything will work again.
Note that, depending on how you use the PrintWriter, this might cause the RegexOutputStreams buffer to get quite big. If you create the PrintWriter to autoflush, it will flush after every line and after every byte array. See its JavaDoc for details.
You could subclass the print stream in question and perform your regexp replacing prior to calling the appropriate super method? E.g.
public void ExampleStream extends PrintStream {
#Override
public void print(String s) {
super(s.replaceAll(ANSI_PATTERN,""));
}
}
I think that the code in Logging class is not a good approach (at least as it is):
If you have access to the PrintStream source code you might find that the methods currently redefined might not being used at all: the PrintStream#print(...) methods delegate on textOut#write(...) (not on the redefined OutputStream#write(...) ).
Therefore, you should redefine the print(String) and print(char[]) methods in order to effectively filter the output.
There are a few examples of redefined methods in the answers (including further down on this one).
Alternatively, if you just want a PrintStream that filters out the ANSI codes (as I originally understood), then it would be more convenient to implement it on a FilterOutputStream (as mthmulders suggests, as you will have to redefine fewer stuff and will be easier to re-use):
Make a copy of BufferedOutputStream class. Name it however you prefer. (E.g. TrimAnsiBufferedStream)
Then redefine de flushBuffer() method:
private void flushBuffer() throws IOException {
if (count > 0) {
String s = new String(buf, 0, count); // Uses system encoding.
s.replaceAll(ANSI_PATTERN, "");
out.write(s.getBytes());
count = 0;
}
}
When you need to instantiate a PrintStream that replaces ANSI, invoke new PrintStream(new TrimAnsiBufferedStream(nestedStream)).
This is probably not bullet-proof (e.g. whatever may happen with encoding configuration, or if buffer size is not big enough, or flushing options in printstream), but I won't overcomplicate it.
By the way. Welcome kukelekuuk00. Just be sure to read the FAQ and feedback on the answers (we care about you, please reciprocate).
I am trying to receive a huge text file as an inputstream and want to convert a string segment with another string. I am strictly confused how to do it, it works well if I convert whole inputstream as a string which I don't want as some of the contents are lost. can anyone please help how to do it??
e.g.
if I have a file which has the contents "This is the test string which needs to be modified". I want to accept this string as input stream and want to modify the contents to "This is the test string which is modified" , ( by replacing 'needs to be' with is).
public static void main(String[] args) {
String string = "This is the test string which needs to be modified";
InputStream inpstr = new ByteArrayInputStream(string.getBytes());
//Code to do
}
In this I want the output as: This is the test string which is modified
Thanking you in advance.
If the text to be changed will always fit in one logical line, as I stated in comment, I'd go with simple Line Reading (if applyable) using something like:
public class InputReader {
public static void main(String[] args) throws IOException
{
String string = "This is the test string which needs to be modified";
InputStream inpstr = new ByteArrayInputStream(string.getBytes());
BufferedReader rdr = new BufferedReader(new InputStreamReader(inpstr));
String buf = null;
while ((buf = rdr.readLine()) != null) {
// Apply regex on buf
// build output
}
}
}
However I've always like to use inheritance so I'd define this somewhere:
class MyReader extends BufferedReader {
public MyReader(Reader in)
{
super(in);
}
#Override
public String readLine() throws IOException {
String lBuf = super.readLine();
// Perform matching & subst on read string
return lBuf;
}
}
And use MyReader in place of standard BufferedReader keeping the substitution hidden inside the readLine method.
Pros: substitution logic is in a specified Reader, code is pretty standard.
Cons: it hides the substitution logic to the caller (sometimes this is also a pro, still it depends on usage case)
HTH
May be I understood you wrong, but I think you should build a stack machine. I mean you can use a small string stack to collect text and check condition of replacement.
If just collected stack already is not matched to your condition, just flush stack to output and collect it again.
If your stack is similar with condition, carry on collecting it.
If your stack is matched your condition, make a modification and flush modified stack to output.