【问题标题】:How to make InputStream skip over a line if it starts with '#'?如果 InputStream 以“#”开头,如何让其跳过一行?
【发布时间】:2017-03-07 20:03:53
【问题描述】:

我正在编写一个必须解码 QR 码的程序。代码在内部表示为 2D 布尔列表。这些代码通常会被读取为包含 1 和 0 的文本文件,其中 1 表示矩阵中的暗模块(真),0 表示亮模块(假)。

我必须实现一个方法,该方法将采用 InputStream,然后必须返回一个 QR 码。我必须阅读包含 1、0 和以“#”开头的注释行的 .txt。我需要让方法忽略那些注释行,但我不知道该怎么做。

以下是代码的一些相关部分:

首先是二维码构造函数(构造函数中使用的所有方法都起作用并完成它们的工作):

public class QRCode {

private List<List<Boolean>> data; //A 2D Boolean matrix, true means black, false means white.

public QRCode(List<List<Boolean>> data)
{
    if (data == null)
        throw new NullPointerException();
    if (QRCode.isQuadratic(data) == false)
        throw new InvalidQRCodeException("Matrix must be quadratic!");
    if (QRCode.versionCheck(data) < 1 || QRCode.versionCheck(data) > 40)
        throw new InvalidQRCodeException("Invalid Dimensions (Version).");
    if (QRCode.correctlyAlligned(data) != true)
        throw new InvalidQRCodeException("Improper Allignment!");
    if (QRCode.correctTimers(data) != true)
        throw new InvalidQRCodeException("Incorrect Timing Pattern!");
    if (QRCode.correctFormatting(data) != true)
        throw new InvalidQRCodeException("Incorrect Formatting!"); 

    this.data = data; 
}   

}

这就是我所指的方法。至少到目前为止我写的。此外,如果 .txt 文件包含除 1、0 和注释以外的任何内容,它应该引发异常。 PS:我以前从未使用过 InputStreams,我尝试使用谷歌搜索,但我找到的所有答案都是针对特定类型的 Streams,并且他们使用 .readLine() 方法,我的 IS 不允许我使用。

public static QRCode fromFile(InputStream is) throws IOException 
{   
    int i;
    List<List<Boolean>> data = new ArrayList<>(); //a 2D Boolean Matrix
    int y = -1, x = -1;

    if (is == null)
        throw new NullPointerException();
    while((i = is.read())!=-1) //Reading begin
    {
        if (i == (byte) '\n') //If a line in .txt file ends.
        {
            y++; 
            data.add(new ArrayList<Boolean>());
            x = 0;
        }

        if ((char) i == '1') //|| (char) i == '0')
        {
            data.get(y).add(true);
            x++;
        }
        if ((char) i == '0') //||
        {
            data.get(y).add(false);
            x++;
        }
    }


    return new QRCode(data);
}

我要处理的文本文件示例:

# name: small
# type: bool matrix
# rows: 25
# columns: 25
1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 0 1 0 1 1 1 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 1
1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1
1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1 0 1 1 1 0 1
1 0 1 1 1 0 1 0 0 0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1
1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1
1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0
1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 1
1 1 1 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 1 0 0 0
1 0 0 1 1 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 1 0 1 0 1
0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 1 1 1 0
0 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 1 0 1 1 0 1 0 1 1
1 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 0
1 1 1 0 0 0 1 1 0 1 0 0 0 1 1 1 1 0 1 0 0 0 0 1 1
1 0 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0 0 1 0 1 1 0 1
1 0 1 1 0 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 1 0 1 1 1
0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1
1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1
1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 0 1 1 0 0 0
1 0 1 1 1 0 1 0 1 0 0 1 0 1 0 1 1 1 1 1 1 1 0 1 1
1 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 0 1 1 1
1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 0 1 1
1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 1

【问题讨论】:

  • 如果您正在阅读文本,您应该使用Reader 而不是InputStream。然后,您可以使用BufferedReader,它有一个readLine() 方法。
  • 问题是,我从作业中给出了这些方法,它必须完全按照给出的方式实现,我无法更改其中的任何内容。
  • 您可以将您的InputStream 转换为BufferedReader,如下所示:new BufferedReader(new InputStreamReader(inputStream));

标签: java multidimensional-array inputstream qr-code


【解决方案1】:

首先,我建议您使用Reader 来阅读文本。然后,您可以使用 BufferedReader 及其 readLine() 方法来处理文本行,而不是字节流。


不管怎样,给定你当前的代码:一旦你读到\n,设置一个布尔标志来表明你刚刚看到了一个换行符。然后,当您开始阅读下一行时,打开该标志,如果它为真,并且您看到 # 作为下一个字符,您应该阅读直到看到另一个 \n。如果它的标志不是真的,那么就像你正在做的那样阅读该行的其余部分。

在查找# 时,您可能需要考虑空格,具体取决于您希望它有多宽松。

【讨论】:

    【解决方案2】:

    为什么不使用Files.lines 而不是InputStream

    Files.lines(Paths.get("path_to_File.txt")).filter(s -> !s.contains("#"));// let's
    //read all lines form the file and skip the lines with `#` symbol
    

    我们可以将每一行转换为Boolean的列表:

    s -> Stream.of(s.split(" ")).map("1"::equals).collect(Collectors.toList())// split 
    string by ` ` (space) symbol and convert to Boolean "1" - true, "0" - false
    

    现在让我们把所有东西放在一起:

    List<List<Boolean>> qr = Files.lines(Paths.get("data/fromFile.txt"))
                    .filter(s -> !s.contains("#")).map(
                            s -> Stream.of(s.split(" ")).map("1"::equals)
                                .collect(Collectors.toList())
                    ).collect(Collectors.toList());
    

    对于文件:

    # name: small
    # type: bool matrix
    # rows: 1
    # columns: 3
    1 1 1
    1 0 1
    

    输出将是

    [true, true, true]
    [true, false, true]
    

    【讨论】:

      【解决方案3】:

      如果您决定使用 Reader,那么您可以使用正则表达式来删除包含除 '0' 和 '1' 之外的任何字符的行。您可以在下面的链接中找到有关正则表达式使用的详细信息。 How to check if a string contains only digits in Java

      您只能修改 1 和 0 的正则表达式,例如 String regex = "[0-1]+";

      您可以使用下面的示例代码来获取每个字符。

      String s1="hello";
      char[] ch=s1.toCharArray();
      

      【讨论】:

        猜你喜欢
        • 2021-12-13
        • 2021-10-07
        • 1970-01-01
        • 2013-09-26
        • 2020-04-02
        • 1970-01-01
        • 2017-08-17
        • 2011-12-13
        • 1970-01-01
        相关资源
        最近更新 更多