I'm working on reading integers into a list in Java, and I found an exception that gets thrown when putting Scanner & nextInt() in the loop.
Exception gets thrown on the Scanner class in this code:
do{
System.out.println("?");
Scanner in = new Scanner(System.in);
input = in.nextInt();
in.close();
if(input != SENTINEL)
numberList.add(input);
}while(input != SENTINEL);
Whereas moving the Scanner initialization and close outside of the loop works just fine:
Scanner in = new Scanner(System.in);
//receive input integers from user
do{
System.out.println("?");
input = in.nextInt();
if(input != SENTINEL)
numberList.add(input);
}while(input != SENTINEL);
in.close();
Why is it that the exception occurs when initializing the Scanner class in the loop? Thanks!
Exception is:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at main.Run.main(Run.java:25)
The reason that the first version crashes is that calling to Scanner.close - also closes the underlying stream: System.in.
It can be proved by wrapping System.in with a class that doesn't do anything in close() method (the code for UnClosableDecorator was taken from here):
public class Play {
public static void main(String[] arg) throws IOException {
int SENTINEL = 10;
int input = 0;
List<Integer> numberList = new ArrayList<>();
System.setIn(new UnClosableDecorator(System.in));
do {
Scanner in = new Scanner(System.in);
System.out.println("?");
input = in.nextInt();
System.out.println("[" + input + "]");
in.close();
if(input != SENTINEL) {
numberList.add(input);
}
} while(input != SENTINEL);
System.out.println("done");
}
}
class UnClosableDecorator extends InputStream {
private final InputStream inputStream;
public UnClosableDecorator(InputStream inputStream) {
this.inputStream = inputStream;
}
#Override
public int read() throws IOException {
return inputStream.read();
}
#Override
public int read(byte[] b) throws IOException {
return inputStream.read(b);
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
return inputStream.read(b, off, len);
}
#Override
public long skip(long n) throws IOException {
return inputStream.skip(n);
}
#Override
public int available() throws IOException {
return inputStream.available();
}
#Override
public synchronized void mark(int readlimit) {
inputStream.mark(readlimit);
}
#Override
public synchronized void reset() throws IOException {
inputStream.reset();
}
#Override
public boolean markSupported() {
return inputStream.markSupported();
}
#Override
public void close() throws IOException {
//do nothing
}
}
Related
In my program I have changed stdout using System.setOut(); but after that, typing into the console no longer echoes the input back.
I tried the following, with no avail:
originalStdIn = System.in;
stdIn = new InputStream() {
#Override
public int available() throws IOException {
return originalStdIn.available();
}
#Override
public int read() throws IOException {
int chr = originalStdIn.read();
stdOut.write(chr);
return chr;
}
#Override
public int read(byte[] buffer) throws IOException {
return this.read(buffer, 0, buffer.length);
}
#Override
public int read(byte[] buffer, int off, int len) throws IOException {
int readResult = originalStdIn.read(buffer, off, len);
stdOut.write(buffer, off, readResult);
return readResult;
}
};
System.setIn(stdIn);
This is how I read input:
private void handleThread_func() {
Logging.didUpdateInWindow = true;
System.out.print(this.consoleInputPrefix);
while (!this.isClosed) {
try {
if (System.in.available() > 0) {
String input = "";
while (System.in.available() > 0) {
input += this.inputReader.readLine();
}
this.handleInput(input);
Logging.didUpdateInWindow = true;
System.out.print(this.consoleInputPrefix);
}
Thread.sleep(1);
} catch (Exception ex) {
if (ex instanceof InterruptedException) break;
Logging.logSevere("Unable to handle console input: " +
Utils.getExceptionStackTraceAsStr(ex));
}
}
}
I tried changing input += this.inputReader.readLine(); to input += (char)this.inputReader.read() but while it did echo, the input was read in the incorrect order
Once user entered data timer stops and BuferredReader closed.
If 10 seconds passed and no input - BuferredReader closed and user unable to make input. Below code works, but not 100% correct.
Please suggest any solution.
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
NewThread nt = new NewThread(br);
Thread newThread = new Thread(nt);
newThread.start();
System.out.print("Please enter data: ");
System.out.println("");
String value = br.readLine();
System.out.println(value);
nt.shutdown();
}
}
class NewThread implements Runnable {
volatile BufferedReader br;
volatile boolean running ;
public NewThread(BufferedReader br) throws IOException {
this.br = br;
this.running = br.ready();
}
#Override
public void run() {
int count = 10;
try {
while (!running) {
System.out.print("("+count +")"+ '\r');
Thread.sleep(1000);
count--;
if (count <0){
shutdown();
}
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
public void shutdown () throws IOException {
running=true;
br.close();
}
}
So, firsty you calling method:
br.readLine()
BufferedReader implementation of this method uses synchornized block when waiting for user input. Below I put part of code this method:
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
...}
Nextly, when you call method shutdown from NewThread(after time out) on your reader, which call close method on buffer - execution of this metod uses synchronized mechanism too:
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
so it means that close method will be executed after finished readLine method (exactly after execution synchronized block in readLine method), which is finished when you pass parameter to console.
I suppose that is not possible to close this reader after calling readLine method by standard java mechanism when you use System.in.
While tinkering around with some I/O stuff, I made an interesting observation: my custom FilterReader seemed to have some unexpected performance overhead. To try and diagnose the issue, I threw together a simple performance test:
import java.io.*;
abstract class Test
{
public final long timeRun(Reader in) throws IOException
{
long start = System.nanoTime();
run(in);
long end = System.nanoTime();
return end - start;
}
protected abstract void run(Reader in) throws IOException;
}
class WrapInFilterTest extends Test
{
private class LetterFilterReader extends FilterReader
{
public LetterFilterReader(Reader in)
{
super(in);
}
#Override
public int read() throws IOException
{
int read;
while ((read = in.read()) != -1)
{
if (Character.isLetter(read))
break;
}
return read;
}
}
#Override
public void run(Reader in) throws IOException
{
try (Reader letterReader = new LetterFilterReader(in))
{
while (letterReader.read() != -1);
}
}
}
class RawReaderTest extends Test
{
#Override
public void run(Reader in) throws IOException
{
while (readLetter(in) != -1);
}
public int readLetter(Reader in) throws IOException
{
int read;
while ((read = in.read()) != -1)
{
if (Character.isLetter(read))
break;
}
return read;
}
}
public class PerformanceTest
{
public static void main(String[] args) throws IOException
{
String filePath = "/path/to/file.txt";
Test[] tests = new Test[] { new WrapInFilterTest(), new RawReaderTest() };
for (Test test : tests)
{
Reader r = new BufferedReader(new FileReader(filePath));
System.out.println(test.timeRun(r) + "ns");
}
}
}
In general, I've found that the custom filter approach can be as much as 3x slower than straight up reading from the buffered reader. However, it seems dependent on the file content. For example, if a file contains strictly letters, I've found that the custom filter approach actually performs marginally faster! What's going on?
I'm using the kubernetes-client to try copy a directory from a pod, but I'm doing something wrong with the input stream from stdout. I get a java.io.IOException: Pipe broken exception when it tries to read(). I'm pretty sure that no data flows at all. I'm half wondering if I need to read the InputStream on a separate thread or something?
The stream is created like this:
public InputStream copyFiles(String containerId,
String folderName) {
ExecWatch exec = client.pods().withName(containerId).redirectingOutput().exec("tar -C " + folderName + " -c");
// We need to wrap the InputStream so that when the stdout is closed, then the underlying ExecWatch is closed
// also. This will cleanup any Websockets connections.
ChainedCloseInputStreamWrapper inputStreamWrapper = new ChainedCloseInputStreamWrapper(exec.getOutput(), exec);
return inputStreamWrapper;
}
And the InputStream is processed in this function
void copyVideos(final String containerId) {
TarArchiveInputStream tarStream = new TarArchiveInputStream(containerClient.copyFiles(containerId, "/videos/"));
TarArchiveEntry entry;
boolean videoWasCopied = false;
try {
while ((entry = tarStream.getNextTarEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
String fileExtension = entry.getName().substring(entry.getName().lastIndexOf('.'));
testInformation.setFileExtension(fileExtension);
File videoFile = new File(testInformation.getVideoFolderPath(), testInformation.getFileName());
File parent = videoFile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
OutputStream outputStream = new FileOutputStream(videoFile);
IOUtils.copy(tarStream, outputStream);
outputStream.close();
videoWasCopied = true;
LOGGER.log(Level.INFO, "{0} Video file copied to: {1}/{2}", new Object[]{getId(),
testInformation.getVideoFolderPath(), testInformation.getFileName()});
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, getId() + " Error while copying the video", e);
ga.trackException(e);
} finally {
if (!videoWasCopied) {
testInformation.setVideoRecorded(false);
}
}
}
The InputStream Wrapper class is just there to close the ExecWatch at the end once the InputStream is closed, it looks like this:
private static class ChainedCloseInputStreamWrapper extends InputStream {
private InputStream delegate;
private Closeable resourceToClose;
public ChainedCloseInputStreamWrapper(InputStream delegate, Closeable resourceToClose) {
this.delegate = delegate;
this.resourceToClose = resourceToClose;
}
#Override
public int read() throws IOException {
return delegate.read();
}
public int available() throws IOException {
return delegate.available();
}
public void close() throws IOException {
logger.info("Shutdown called!");
delegate.close();
// Close our dependent resource
resourceToClose.close();
}
public boolean equals(Object o) {
return delegate.equals(o);
}
public int hashCode() {
return delegate.hashCode();
}
public int read(byte[] array) throws IOException {
return delegate.read(array);
}
public int read(byte[] array,
int n,
int n2) throws IOException {
return delegate.read(array, n, n2);
}
public long skip(long n) throws IOException {
return delegate.skip(n);
}
public void mark(int n) {
delegate.mark(n);
}
public void reset() throws IOException {
delegate.reset();
}
public boolean markSupported() {
return delegate.markSupported();
}
public String toString() {
return delegate.toString();
}
}
Turns out I had the tar command wrong, so it was causing a failure and the stdout PipeInputStream was dead locking. I managed to find a workaround for the deadlock. But the main reason for the failure was that I forgot to tell tar to actually do something! I at least needed a "." to include the current directory.
I am trying to use the JTape Library to read some data from a DDS4 magnetic tape.
I want to use eclipse to run my code under Linux 12.04 LTS
The problem is that I cannot let eclipse reference the TapeLinux.c Library in any way.
PROBLEM:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no TapeLinux in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at BasicTapeDevice.<clinit>(BasicTapeDevice.java:169)
at TestEOD.main(TestEOD.java:12)
This are my classes:
/* TestEOD.java */
import java.io.*;
public class TestEOD {
public static void main(String[] args) throws IOException {
/* if (args.length != 1) {
System.err.println("Usage: java TestEOD <path to device>");
System.exit(1);
}*/
BasicTapeDevice d = new BasicTapeDevice("/dev/nst0");
System.out.print("Rewinding...");
System.out.flush();
d.rewind();
System.out.println("done!");
System.out.print("Spacing to end of data...");
System.out.flush();
d.spaceEOD();
System.out.println("done!");
}
}
/* BasicTapeDevice.java */
import java.io.*;
public class BasicTapeDevice {
private FileDescriptor fd;
private InputStream in;
private OutputStream out;
private boolean eof;
private boolean eom;
private boolean ignoreEOM;
public BasicTapeDevice(String pathName) throws IOException {
fd = new FileDescriptor();
tapeOpen(pathName);
in = new TapeInputStream();
out = new TapeOutputStream();
eof = false;
eom = false;
ignoreEOM = false;
}
public synchronized void close() throws IOException {
if (fd != null) {
try {
if (fd.valid()) {
tapeClose();
}
} finally {
fd = null;
}
}
}
public InputStream getInputStream() throws IOException {
ensureOpen();
return in;
}
public OutputStream getOutputStream() throws IOException {
ensureOpen();
return out;
}
public int getBlockSize() throws IOException {
ensureOpen();
return tapeGetBlockSize();
}
public void setBlockSize(int bs) throws IOException {
ensureOpen();
tapeSetBlockSize(bs);
}
public void rewind() throws IOException {
ensureOpen();
tapeRewind();
}
public void spaceEOD() throws IOException {
ensureOpen();
tapeSpaceEOD();
}
public void clearEOF() throws IOException {
ensureOpen();
if (eof) {
eof = false;
/* assume that the file mark has already been skipped */
} else {
throw new IOException("not at end of file");
}
}
public void clearEOM() throws IOException {
ensureOpen();
if (eom) {
ignoreEOM = true;
} else {
throw new IOException("not at logical end of media");
}
}
class TapeInputStream extends InputStream {
private byte[] temp = new byte[1];
public int read() throws IOException {
int n = read(temp, 0, 1);
if (n <= 0) {
return -1;
}
return temp[0] & 0xff;
}
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (off < 0 || len < 0 || off+len > b.length) {
throw new IndexOutOfBoundsException();
}
if (len == 0) {
return 0;
}
if (eof) {
return -1;
}
ensureOpen();
int n = tapeRead(b, off, len);
if (n <= 0) {
return -1;
}
return n;
}
public long skip(long numbytes) throws IOException {
return 0;
}
public void close() throws IOException {
BasicTapeDevice.this.close();
}
}
class TapeOutputStream extends OutputStream {
private byte[] temp = new byte[1];
public void write(int b) throws IOException {
temp[0] = (byte) b;
write(temp, 0, 1);
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (off < 0 || len < 0 || off+len > b.length) {
throw new IndexOutOfBoundsException();
}
if (eom && !ignoreEOM) {
throw new LogicalEOMException("logical end-of-media");
}
int n = tapeWrite(b, off, len);
while (n < len) {
n += tapeWrite(b, off + n, len - n);
}
}
public void close() throws IOException {
BasicTapeDevice.this.close();
}
}
protected void finalize() {
try {
close();
} catch (IOException ex) {
}
}
private void ensureOpen() throws IOException {
if (fd == null || !fd.valid()) {
throw new IOException("tape device is not open");
}
}
private static native void initFields();
private native void tapeOpen(String pathName) throws IOException;
private native void tapeClose() throws IOException;
private native int tapeRead(byte[] b, int off, int len) throws IOException;
private native int tapeWrite(byte[] b, int off, int len) throws IOException;
private native int tapeGetBlockSize() throws IOException;
private native void tapeSetBlockSize(int bs) throws IOException;
private native void tapeRewind() throws IOException;
private native void tapeSpaceEOD() throws IOException;
/* load the JNI library specific for this platform */
static {
StringBuffer buf = new StringBuffer("Tape");
String osName = System.getProperty("os.name");
if (osName.equals("Windows NT") || osName.equals("Windows 2000")) {
buf.append("WinNT");
} else {
buf.append(osName);
}
System.loadLibrary(buf.toString());
initFields();
}
}
WHAT I HAVE TRIED
I have looked around that what I need is to include the path of the folder which contains the file TapeLinux.c
I have tried all these answers and nothing change
Can you please help me to figure out how I can use JNI in this situation and what I should configure to run my code
Thanks
Since you are on Linux, the message ...main java.lang.UnsatisfiedLinkError: no TapeLinux in java... likely means the library named libTapeLinux.so could not be found.
Seems you are searching for a solution by trying to locate TapeLinux.c and you should be searching for libTapeLinux.so and once you find it make sure libTapeLinux.so is on the load path.