Enter & Ioerror: Byte Oriented Read for Character Buffered Io

enter & IOError: byte oriented read for character buffered IO

The code from that answer is a simplified version of a highline-like library I wrote for personal use. I never encountered that specific error myself, but it might be due to the fact I'm actually using something slightly different. My actual code goes something more like this:

require 'io/console'
require 'io/wait'

catch(:done) do
loop do
chars = STDIN.getch
chars << STDIN.getch while STDIN.ready? # Process multi-char paste
throw :done if ["\r", "\n", "\r\n"].include?(chars)
STDOUT.print chars
end
end
STDOUT.print "\n"

I also have kill-signal handler, in case Ctrl+C (kill process) or Ctrl+D (end of input) get pressed; the first interrupts the program, and the second is wired to react as if enter was pressed.

The precise behavior might depend on the OS (I use it on OSX and FreeBSD), since the enter key could return any of "\r", "\n" or "\r\n" depending on the OS:

\r\n , \r , \n what is the difference between them?

Ruby skipping gets after previous gets with parameter

Kernel#gets can actually take an argument, a separator. This tells Ruby when to stop reading from stdin. If you don't provide this argument, the default value of \n ($/) is used. Here's what happens when your program runs:

  • gets asks for everything until the first done.
  • You type something, then type done, then hit enter. This is key, because now the input stream ends with done\n but gets has only read up till done.
  • gets asks for everything until the first \n This \n is found immediately after the done, and gets already has it because you already typed it so it doesn't ask you for any more.

That's why you're not getting a chance to input anything after the first gets. To eliminate this problem, you should make the separator "done\n", or perhaps "\ndone\n", if you want it to strictly be on its own line.

gets.chomp without moving to a new line

You can do this by using the (very poorly documented) getch:

require 'io/console'
require 'io/wait'

loop do
chars = STDIN.getch
chars << STDIN.getch while STDIN.ready? # Process multi-char paste
break if ["\r", "\n", "\r\n"].include?(chars)
STDOUT.print chars
end

References:

  • http://ruby-doc.org/stdlib-2.1.0/libdoc/io/console/rdoc/IO.html#method-i-getch
  • http://ruby-doc.org/stdlib-2.1.0/libdoc/io/wait/rdoc/IO.html#method-i-ready-3F

Related follow-up question:

enter & IOError: byte oriented read for character buffered IO

How to get a single character without pressing enter?

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/2999

#!/usr/bin/ruby

begin
system("stty raw -echo")
str = STDIN.getc
ensure
system("stty -raw echo")
end
p str.chr

(Tested on my OS X system, may not be portable to all Ruby platforms). See http://www.rubyquiz.com/quiz5.html for some additional suggestions, including for Windows.

What is the use of System.in.read()?

May be this example will help you.

import java.io.IOException;

public class MainClass {

public static void main(String[] args) {
int inChar;
System.out.println("Enter a Character:");
try {
inChar = System.in.read();
System.out.print("You entered ");
System.out.println(inChar);
}
catch (IOException e){
System.out.println("Error reading from user");
}
}
}

remove characters from EOL

The printf() is behaving in an interesting fashion when it sees a \r\n rather than a lone \n. It interprets the paired character end-of-line as not an end-of-line and so rather than doing the usual end-of-line-function, it shows you a ^M^J. Simple eliminating the \r will then give you the desired behavior.

  char buff[150];
int n = read(fd,buff,sizeof(buff)); // buff is not NUL terminated
if (n < 0) {
// deal with I/O error
}
if (n == 0) {
// deal with end-of-file
}
else {
for (int i=0; i<n; i++) {
if (isprint(buff[i]) || (buff[i] == '\n')) {
putchar(buff[i]);
}
else if (buff[i] == '\r') {
; // drop it
}
else {
; // TBD deal with unexpected control codes and codes 127-255
}
}
}

Notes:

1) You filled buff before from the serial device using a read(). As serial devices are binary, the bytes read may include NUL bytes. Reading an array of bytes with sporadically intersperse NUL bytes in a buffer and treating it like a NUL terminated character string will lead to missed data.

2) A read() does not append a \0 byte to the end of the buffer it reads and may explain your "ERROR".

3) In general, you are reading a binary device and writing to a textual output. The incoming binary stream is likely ASCII text using \r\n as an end-of-line but your stdout wants to use \n as end-of-line. As long as the bytes are printable ASCII (codes 32-126), all works as expected when printing to stdout. But when you read a \0, \r, \n, paired \r\n, other control characters, communication errors, etc., you need to consider how you want that displayed.



Related Topics



Leave a reply



Submit