2016-05-22 113 views

回答

1

这是因为它等待一个EOF(文件的结束)。所以你需要先关闭套接字。

读取所有字节,直到EOF在这个源代码中,将它们放入buf。

我认为这是可行与(你提到你自己的方法)焦炭更好地char

fn chars(self) -> Chars<Self> 

创建这种方法的迭代器,并检查您的分隔符。

bytes

fn bytes(self) -> Bytes<Self> 
+1

但他们也期待EOF。 –

6

有没有更好的方式来读取,直到当前的字符是CR或LF?

是的。逐字节读取通常不是一个好主意。通常,您想要读取缓冲区,以减少系统调用次数。

使用read_to_endread_to_string需要分配足够的内存来读取所有内容,这可能是一个DoS缺陷。

一种选择是编写自己的缓冲机制,执行连续调用read。这可能很乏味。

您可以使用BufReader来为任何读者添加缓冲,而不是编写自己的缓冲机制。 BufReader执行BufRead,它具有方法read_until,可用于读取特定字节,但不能直接使用此方法,因为您有兴趣直到读取b'\n'b'\r'。但是您可以编写一个实现Read,将b'\r'翻译为b'\n',然后使用read_untilb'\n'。下面是一个如何可以做到这一点一个例子:

use std::io::{self, Read, BufRead, BufReader}; 

pub struct ReadCrToLf<R: Read>(R); 

impl<R: Read> Read for ReadCrToLf<R> { 
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> { 
     self.0.read(buffer).map(|s| { 
      for x in &mut buffer[..s] { 
       if *x == b'\r' { 
        *x = b'\n'; 
       } 
      } 
      s 
     }) 
    } 
} 

fn main() { 
    let read = b"test1\ntest2\rtest3\n"; 
    let rt = ReadCrToLf(&read[..]); 
    let mut reader = BufReader::new(rt); 
    let mut buffer = Vec::new(); 

    reader.read_until(b'\n', &mut buffer).unwrap(); 
    assert_eq!(buffer, b"test1\n"); 
    buffer.clear(); 

    reader.read_until(b'\n', &mut buffer).unwrap(); 
    assert_eq!(buffer, b"test2\n"); 
    buffer.clear(); 

    reader.read_until(b'\n', &mut buffer).unwrap(); 
    assert_eq!(buffer, b"test3\n"); 
} 

,如果你需要,因为你的分隔符只是ASCII字符(字节)b'\n'b'\r'

+0

这也是困难的。 –

+0

everything ...... –

+0

'n一般情况下,你想读取一个缓冲区,所以你减少了系统调用的次数。“---你为什么认为'self.0.read(buffer).map(| s | {....'有较少的系统调用数量? –

3

来区分你能适应这种解决方案,您可以使用Read::bytesBufReader。没有缓冲读取,bytes()方法效率非常低,因为系统调用是为每个字节读取完成的。

bytes()顶部,你可以使用标准的迭代方法,像这样:

let buf_socket = BufReader::new(&socket); 
let data: Vec<_> = buf_socket.bytes() 
    .take_while(|b| { 
     match *b { 
      Err(_) | Ok(b'\n') | Ok(b'\r') => false, 
      _ => true, 
     } 
    }) 
    .collect(); 

这工作,因为迭代器是懒惰,比目前所需要的Bytes迭代器无法读取更多的数据。

+1

对我来说太困难了。 –