从 InputStream 中删除换行符

Posted

技术标签:

【中文标题】从 InputStream 中删除换行符【英文标题】:Removing newline characters from InputStream 【发布时间】:2013-01-23 00:59:40 【问题描述】:

我喜欢从java.io.InputStream 中删除所有换行符(对于 \n 和 \r\n),在读取文件时,相应的方法如下所示:

/**
 * @param target @linkplain File
 * @return @linkplain InputStream
 * @throws Exception
 */
protected InputStream initInput(final File file)
    throws Exception 
    InputStream stream = null;
    try 
        if (file.isDirectory()) 
            // throw exception
        
        if (!file.exists()) 
            // throw another exception
        
        // 
        // *remove newlines here*
        //
        stream = new FileInputStream(file);

     catch (FileNotFoundException e) 
        // throw another exception
    
    return stream;

【问题讨论】:

【参考方案1】:

有时,标准 Java 库无法提供足够的方法来操作其核心类。 Apache Commons Lang 提供了这些额外的方法。

如果您可以使用该库,StringUtils.chomp 方法可能有用。

【讨论】:

【参考方案2】:

您可以拥有自己的java.io.FileInputStream 实现并以一种在阅读时跳过\r\n 的方式覆盖读取方法。

Hier 是示例实现(没有任何错误处理)

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class NoNewLineFileInputStream extends FileInputStream 

    public NoNewLineFileInputStream(String filepath) throws FileNotFoundException 
        super(filepath);
    

    public NoNewLineFileInputStream(File file) throws FileNotFoundException 
        super(file);
    

    public NoNewLineFileInputStream(FileDescriptor filedescriptor) 
        super(filedescriptor);
    

    @Override
    public int read(byte[] b) throws IOException 
        return this.read(b, 0, b.length);
    

    @Override
    public int read(byte[] b, int off, int len) throws IOException 
        int n = 0, c;
        do 
            c = this.read();
            if(c != -1) 
                b[off + n] = (byte) c;
                n++;
                len--;  
             else 
                return c;
            
         while(c != -1 && len > 0);
        return n;
    


    @Override
    public int read() throws IOException 
        int c;
        do 
            c = super.read();
         while(c != -1 && (c == '\n' || c == '\r'));
        return c;
    

对于一些基本的测试......

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import junit.framework.Assert;

import org.junit.BeforeClass;
import org.junit.Test;

public class NoNewLineFileInputStreamTest 

    private final static String txt = "testnl.txt";

    @BeforeClass
    public static void genTestFile() throws IOException 
        OutputStream os = new FileOutputStream(txt);
        os.write((
                "Hello\n" +
                ",\r\n" +
                "World!\r" +
                "").getBytes());
        os.close();
    

    @Test
    public void readInt() throws IOException 
        InputStream is = new NoNewLineFileInputStream(txt);
        int c = is.read();
        while(c != -1) 
            Assert.assertTrue(c != '\n' && c != '\r');
            c = is.read();
        
        is.close();
    

    @Test
    public void readBytes() throws IOException 
        InputStream is = new NoNewLineFileInputStream(txt);
        int l = is.available();
        if(l > 0) 
            byte[] content = new byte[l];
            int n = is.read(content);
            String expected = "Hello,World!";
            Assert.assertEquals(expected.getBytes().length, n);
            Assert.assertEquals(expected, new String(content, 0, n));
        
        is.close();
    

    @Test
    public void readBytesOffset() throws IOException 
        InputStream is = new NoNewLineFileInputStream(txt);
        int l = is.available();
        if(l > 0) 
            byte[] content = new byte[l*3];
            int n = is.read(content, 3, 5);
            String expected = "Hello";
            Assert.assertEquals(expected.getBytes().length, n);
            Assert.assertEquals(expected, new String(content, 3, n));
        
        is.close();
    

你的方法应该是这样的

/**
 * @param target @linkplain File
 * @return @linkplain InputStream
 * @throws Exception
 */
protected InputStream initInput(final File file)
    throws Exception 
    InputStream stream = null;
    try 
        if (file.isDirectory()) 
            // throw exception
        
        if (!file.exists()) 
            // throw another exception
        
        // 
        // read operations using this implementation will jump over all '\n' and '\r'
        //
        stream = new NoNewLineFileInputStream(file);

     catch (FileNotFoundException e) 
        // throw another exception
    
    return stream;

为了更好地兼容 java.io.InputStream 抽象类,您可能希望在您的类中覆盖它的所有方法。

【讨论】:

【参考方案3】:

您可以将其转换为字符串,并将换行符替换为空:

InputStream is = new ByteArrayInputStream("file content".getBytes());

    //read it with BufferedReader
    BufferedReader br  = new BufferedReader(new InputStreamReader(is));

    StringBuilder sb = new StringBuilder();

    String line;
    while ((line = br.readLine()) != null) 
        sb.append(line.replace("\r","").replace("\n",""))       


    System.out.println(sb.toString());

考虑到您的文本不包含与您相关的“\n”和“\r”,这会很好。

【讨论】:

以上是关于从 InputStream 中删除换行符的主要内容,如果未能解决你的问题,请参考以下文章

从 fgets() 输入中删除尾随换行符

怎么从InputStream流中逐行读取,即遇换行再读取

取消从 InputStream 读取

替换换行符 sed [重复]

有没有办法删除数组中字符串中的换行符?

使用 sed 从传入流中删除换行符