【问题标题】:Java: Reading a file, first line missingJava:读取文件,第一行丢失
【发布时间】:2013-12-31 02:11:19
【问题描述】:

我有一个HashMap<String, String>,它保存了图像的文件名和显示名称。我逐行读取文件并将键和值添加到 HashMap。

BufferedReader reader;
String line;
String[] lineSplit;

HashMap<String, String> imenaZnaki = new HashMap<String, String>();

try {
    reader = new BufferedReader(new InputStreamReader(am.open("znaki_imena.txt"), "UTF-8"));
    line = reader.readLine();
    while (line != null) {
        lineSplit = line.split("->");
        imenaZnaki.put(lineSplit[0], lineSplit[1]);
        line = reader.readLine();
    }
    reader.close();
} catch (IOException e) {
    e.printStackTrace();
}

一切都按预期工作,除了第一个添加的条目,.get(key) 返回 null 并且 .containsKey(key) 返回 false。所有其他键/值都可以正常工作并正确存储在 HashMap 中。

编辑:

这根本没有意义......在我将内容添加到 HashMap 后,我运行了 MagicMan 提供的代码来检查所有条目是否都在 HashMap 内

for(String key: imenaZnaki.keySet()) {
    System.out.println("KEY: " + key + "  VALUE: " + imenaZnaki.get(key));
}

如果我将 CTRL + F 用于“nevar_andrej”,它会显示 4 个输出,这是正确的。但是,如果我搜索“nevar_andrej”(带有空格),它只会显示其中的 3 个,这是错误的,因为第一个会丢失。所以我的猜测是,文件的第一行中有一些东西会引起混淆。所以我添加了一个虚拟/假的第一行(bla_bla->Bla bla)并且它有效,但这是一个讨厌的解决方法。

这是我用 UTF-8 http://pastebin.com/6A4r4jm6 编码的全文文件

【问题讨论】:

  • 在调试器中单步执行。 getcontainsKey不太可能存在存储 Strings 的错误。
  • 使用 HashMap.keySet() 转储映射中的键集。你确定你的钥匙不在里面吗?很有可能这是某种编码错误 - 我猜你测试的“nevar_andrejev ...”字符串的版本与文件中的实际内容略有不同。您可以尝试在十六进制阅读器中查看您的源代码和文本文件,以比较字符串并确保它们逐字节相同。
  • @user2339071 - java 中的数组不会增长。您可以创建一个更大的新数组,但它们不会增长。此时,您会注意到 lineSplit 来自 String.split() 函数,该函数每次调用时都会分配一个新数组。
  • "Unicode" 在这里表示 UTF-16 ("Unicode" 不是一种编码 - 它是一个为字形和字形修饰符分配值的系统;它没有提到如何将这些值存储在磁盘上或在内存中); Microsoft 有时可能很愚蠢。 C# 在内部将值存储为 UTF-16,因此当您复制内容以放入文本文件和代码时,可能会出现问题,而且碰巧它使用 UTF-16 时可以正常工作。 UTF-8 和 UTF-16 都完全能够代表整个 unicode 代码空间。
  • 在意识到我对编码的了解真的很差之后,我偶然发现了一篇很棒的文章,标题是:每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最小值(没有借口!)@987654322 @

标签: java android hashmap


【解决方案1】:

尝试运行下面的代码,看看是否所有条目都存在:

for(String key: imenaZnaki.keySet()) {
        System.out.println("KEY: " + key + "  VALUE: " + imenaZnaki.get(key));
}

我能够运行您的代码和示例,并让所有 7 个条目在其中弹出。如果对您不起作用,请参阅 antiduh 的评论;您在 get() 调用中使用的字符串可能遇到编码问题。

这是从 OS X 运行的,

指定 UTF-8 作为格式的控制台输出:

KEY: nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna  VALUE: Andrejev kri? (?elezni?ka proga je dvo ali ve?tirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna_2  VALUE: Andrejev kri? (?elezni?ka proga je dvo ali ve?tirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_enotirna  VALUE: Andrejev kri? (?elezni?ka proga je enotirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_enotirna_2  VALUE: Andrejev kri? (?elezni?ka proga je enotirna)
KEY: nevar_blizina_letaliske_steze  VALUE: Bli?ina letali?ke steze
KEY: nevar_blizina_obale  VALUE: Bli?ina obale
KEY: nevar_blizina_svetlobnih_prometnih_znakov  VALUE: Bli?ina svetlobnih prometnih znakov

更新

所以这似乎是正在读取 BOM(http://en.wikipedia.org/wiki/Byte_order_mark) 的问题。我最初将文件重新保存为 UTF-8,它产生了上面的输出。然后我用编码“UTF-8 with BOM”重新保存了文件,它产生了这个:

KEY: ???nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna  VALUE: Andrejev kri?? (??elezni??ka proga je dvo ali ve??tirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna_2  VALUE: Andrejev kri?? (??elezni??ka proga je dvo ali ve??tirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_enotirna  VALUE: Andrejev kri?? (??elezni??ka proga je enotirna)
KEY: nevar_andrejev_kriz_zelezniska_proga_je_enotirna_2  VALUE: Andrejev kri?? (??elezni??ka proga je enotirna)
KEY: nevar_blizina_letaliske_steze  VALUE: Bli??ina letali??ke steze
KEY: nevar_blizina_obale  VALUE: Bli??ina obale
KEY: nevar_blizina_svetlobnih_prometnih_znakov  VALUE: Bli??ina svetlobnih prometnih znakov

注意这三个?第一行前面的字符。这些是十六进制的 BOM 字符:EF BB BF。这可能是导致您在第一行出现问题的原因。尝试使用 Notepad++ 或 SublimeText 等文本编辑器在没有 BOM 的情况下重新保存文件

【讨论】:

  • 第二个问题,一定是某个地方的编码问题造成了不平等。
  • 阅读我编辑的关于进一步“调查”的问题;)
  • 最初我使用的是普通的记事本,下载记事本++后我按照你说的做了,它就像一个魅力。不知道这可能是一个问题。感谢您的帮助!
【解决方案2】:

我打电话给Shennanegans...

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map.Entry;

public class main {

public static void main(String[] args) {
    BufferedReader reader;
    String line;
    String[] lineSplit;

    HashMap<String, String> imenaZnaki = new HashMap<String, String>();

    try {
        reader = new BufferedReader(new FileReader(new File("test.txt")));
        String firstKey, firstValue;
        firstKey = null;
        firstValue = null;
        line = reader.readLine();
        while (line != null) {
            lineSplit = line.split("->");
            if (firstKey == null) {
                firstKey = lineSplit[0];
                firstValue = lineSplit[1];
            }
            imenaZnaki.put(lineSplit[0], lineSplit[1]);
            line = reader.readLine();
        }
        reader.close();

        System.out.println("contains first split line key: " +  imenaZnaki.containsKey(firstKey));
        System.out.println("contains first split key text dupe: " + imenaZnaki.containsKey("nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna"));
        for (Entry<String, String> entry : imenaZnaki.entrySet()) {
            System.out.println("key: " + entry.getKey() + " " + "value: " + entry.getValue());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

}

控制台输出:

contains first split line key: true
contains first split key text dupe: true
key: nevar_blizina_letaliske_steze value: Bližina letališke steze
key: nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna_2 value: Andrejev križ (železniÅ¡ka proga je dvo ali veÄ?tirna)
key: nevar_andrejev_kriz_zelezniska_proga_je_enotirna value: Andrejev križ (železniška proga je enotirna)
key: nevar_blizina_obale value: Bližina obale
key: nevar_blizina_svetlobnih_prometnih_znakov value: Bližina svetlobnih prometnih znakov
key: nevar_andrejev_kriz_zelezniska_proga_je_dvo_ali_vectirna value: Andrejev križ (železniÅ¡ka proga je dvo ali veÄ?tirna)
key: nevar_andrejev_kriz_zelezniska_proga_je_enotirna_2 value: Andrejev križ (železniška proga je enotirna)

【讨论】:

  • 你的输出是乱码 - 你也有编码问题:)
  • 我没有指定编码,所以我希望它将保存文件 test.txt 的 UTF-8 转换为带有文字的源代码中的 win-1252,以及作为变量。
【解决方案3】:

我认为问题不在哈希图中 在文件格式里面,我把文件格式改成GBK以及相关的阅读代码,我可以访问密钥

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多