【问题标题】:How can I read characters until a specific one in Java?如何在 Java 中读取特定字符之前的字符?
【发布时间】:2018-10-26 22:38:39
【问题描述】:

我想从文件中读取几个单词。我没有找到任何方法来做到这一点,所以我决定逐个字符地读取 char,但我需要在空格处停下来将读取的单词存储在我的数组中并转到下一个。

我正在制作一个外部排序应用程序,这就是我有内存限制的原因,在这种情况下,我不能只使用readLine() 然后split(),我需要控制我的内容阅读。

read() 方法返回一个 int,我不知道我可以做什么来处理 read() 方法返回一个 char 并在空格后停止读取。

到目前为止,这是我的代码:

protected static String [] readWords(String arqName, int amountOfWords) throws IOException {
    FileReader arq = new FileReader(arqName);
    BufferedReader lerArq = new BufferedReader(arq);

    String[] words = new String[amountOfWords];

    for (int i = 0; i < amountOfWords; i++){
        //words[i] = lerArq.read();
    }

    return words;
}

编辑 1: 我使用了 Scannernext() 方法,它起作用了。 Scanner 的初始化在 Main。

static String [] readWords(int amountOfWords, Scanner leitor) throws IOException {
    String[] words= new String[amountOfWords];

    for (int i = 0; i < amountOfWords; i++){
        words[i] = leitor.next();
    }

    return words;
}

【问题讨论】:

  • 使用nextLine()函数逐行读取,然后调用split(" ")生成单词数组,假设单词之间只用一个空格隔开
  • 您可以使用Scanner.next() 一次阅读一个单词。例如tutorialspoint.com/java/util/scanner_next.htm
  • @RAZ_Muh_Taz 我很感谢这个答案,但正如我在问题中所说,由于内存限制,我不能只使用 nextLine()。
  • @SergeiSirik 我会试试的,谢谢!

标签: java file char external-sorting


【解决方案1】:

也许这会有所帮助。

使用read() 没有问题。只需将结果转换为一个字符:

...
for (int i = 0; i < memTam; i++) {
      // this should work. you will get the actual character
      int current = lerArq.read();
      if (current != -1) {
          char c = (char) current;
          // then you can do what you need with this character
      }
}
...

该方法将读取的字符返回为 0 到 65535 范围内的整数,如果已到达流的末尾,则返回 -1。

我不会添加很多关于编码的理论,它是如何在 Java 中完成的,等等,因为我不知道一些非常低级的细节。我对它的工作原理有一个基本的高级理解。

键盘上的每个键都有一个与之关联的数字。您键入的每个字符都可以转换为十进制数。例如,A 变为数字 65。这是一个标准,是全球公认的。

在这一点上,我希望你能同意read() 方法返回一个数字而不是实际字符并不是那么奇怪:)

有一种叫做 ASCII 表的东西,它代表了键盘上所有键的所有代码(数字)。

这里只是为了展示 ot 的外观:

Dec  Char                           Dec  Char     Dec  Char     Dec  Char
---------                           ---------     ---------     ----------
  0  NUL (null)                      32  SPACE     64  @         96  `
  1  SOH (start of heading)          33  !         65  A         97  a
  2  STX (start of text)             34  "         66  B         98  b
  3  ETX (end of text)               35  #         67  C         99  c
  4  EOT (end of transmission)       36  $         68  D        100  d
  5  ENQ (enquiry)                   37  %         69  E        101  e
  6  ACK (acknowledge)               38  &         70  F        102  f
  7  BEL (bell)                      39  '         71  G        103  g
  8  BS  (backspace)                 40  (         72  H        104  h
  9  TAB (horizontal tab)            41  )         73  I        105  i
 10  LF  (NL line feed, new line)    42  *         74  J        106  j
 11  VT  (vertical tab)              43  +         75  K        107  k
 12  FF  (NP form feed, new page)    44  ,         76  L        108  l
 13  CR  (carriage return)           45  -         77  M        109  m
 14  SO  (shift out)                 46  .         78  N        110  n
 15  SI  (shift in)                  47  /         79  O        111  o
 16  DLE (data link escape)          48  0         80  P        112  p
 17  DC1 (device control 1)          49  1         81  Q        113  q
 18  DC2 (device control 2)          50  2         82  R        114  r
 19  DC3 (device control 3)          51  3         83  S        115  s
 20  DC4 (device control 4)          52  4         84  T        116  t
 21  NAK (negative acknowledge)      53  5         85  U        117  u
 22  SYN (synchronous idle)          54  6         86  V        118  v
 23  ETB (end of trans. block)       55  7         87  W        119  w
 24  CAN (cancel)                    56  8         88  X        120  x
 25  EM  (end of medium)             57  9         89  Y        121  y
 26  SUB (substitute)                58  :         90  Z        122  z
 27  ESC (escape)                    59  ;         91  [        123  {
 28  FS  (file separator)            60  <         92  \        124  |
 29  GS  (group separator)           61  =         93  ]        125  }
 30  RS  (record separator)          62  >         94  ^        126  ~
 31  US  (unit separator)            63  ?         95  _        127  DEL

所以,假设您有一个带有一些文本的 .txt 文件 - 所有字母都有对应的数字。

ASCII 的问题在于 ASCII 定义了 128 个字符,这些字符映射到数字 0-127(所有的大写字母、小写字母、0-9 位数字和更多符号)。

但世界上有更多不同的字符/符号(不同的字母、表情符号等),因此必须有另一种编码系统来表示它们。

它被称为 Unicode。对于代码为 0-127 的字符,Unicode 完全相同。但总的来说,Unicode 可以表示范围更广的符号。

在 Java 中,char 数据类型(以及 Character 对象封装的值)基于原始 Unicode 规范,该规范将字符定义为固定宽度的 16 位实体。您可以在此javadoc 中查看更多详细信息。 换句话说,Java 中的所有字符串都以 UTF-16 表示。

希望,经过这个长篇大论之后,为什么您在阅读时会得到数字是有道理的,但是您可以将它们转换为类型 char。再说一次,这只是一种高级概述。快乐编码:)

【讨论】:

  • 嗯,其实char是一个UTF-16编码单元值。 UTF-16 是Unicode 字符集的几种编码之一。 FileReader 使用系统默认编码并转换为 UTF-16。系统默认编码在哪里以及如何有用是另一个问题。
  • @TomBlodget 这是一个非常好的评论。您对 UTF-16 的看法是绝对正确的,但 Unicode 是 ASCII 的超集,数字 0-128 在 ASCII 中的含义与它们在 Unicode 中的含义相同。我对吗 ?我的想法只是基本上解释了即使该方法返回整数它实际上是一个字符并且可以这样使用。但也许我必须更明确。
  • 用错误的字符编码解释数字是否有意义? (从教条上讲,不,但从教学上讲,是的——只要学习者已经知道 ASCII;但没有任何特别的理由,除非他们使用 RFC 7231 或其他标准。)
  • @TomBlodget 不同意。没有关于编码的东西(比如Java使用ASCII作为字符串左右),但我还是更新了我的答案。如果你有时间,欢迎你来看看)
【解决方案2】:

如果您想逐个字符地读取它(这样您可以更好地控制要存储的内容和不存储的内容),您可以尝试这样的操作:

import java.io.BufferedReader;
import java.io.IOException;

[...]

public static String readNextWord(BufferedReader reader) throws IOException {
    StringBuilder builder = new StringBuilder();

    int currentData;

    do {
        currentData = reader.read();

        if(currentData < 0) {
            if(builder.length() == 0) {
                return null;
            }
            else {
                return builder.toString();
            }
        }
        else if(currentData != ' ') {
            /* Since you're talking about words, here you can apply
             * a filter to ignore chars like ',', '.', '\n', etc. */

            builder.append((char) currentData);
        }

    } while (currentData != ' ' || builder.length() == 0);

    return builder.toString();
}

然后这样称呼它:

String[] words = new String[amountOfWordsToRead];

for (int i = 0; i < amountOfWordsToRead; i++){
    words [i] = readNextWord(yourBufferedReader);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2022-11-10
    • 2014-05-22
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多