我已经创建了从csv文件中读取数据的代码。但是,我无法处理像£这样的特殊字符。
例如,My Base Cost (K£)
被视为My Base Cost (K£)
。
我该怎么做才能纠正这个问题?
public void parseCSVFile(String filename){
try {
br = new BufferedReader(new FileReader(csvDirectory + filename));
while ((parsedLines = br.readLine()) != null) {
String[] parsedData = parsedLines.split(csvSplitByComma);
entireFeed.add(parsedData[0]);
entireFeed.add(parsedData[1]);
System.out.println(parsedData[0]);
System.out.println(parsedData[1]);
it = entireFeed.iterator();
}
} catch (Exception e) {
e.printStackTrace();
}
}
答案 0 :(得分:3)
编写CSV的代码已损坏。它在UTF-8中以三重编码编写了文本。
在UTF-8中,ASCII字符(代码点0-127)表示为单个字节;他们不需要编码。这就是为什么只有£
受到影响的原因。
£
需要UTF-8中的两个字节。这些字节是:0xc2,0xa3。如果编写CSV文件的代码正确使用了UTF-8,则该字符将显示为文件中的这两个字节。
但是,显然,某些代码使用单字节字符集(如ISO-8859-1)读取文件,导致每个字节被视为自己的字符。然后使用UTF-8对这些单个字符进行编码。意思是,在UTF-8中花了{0xc2,0xa3}字节和编码每个。这又产生了这些字节:0xc3,0x82,0xc2,0xa3。 (具体来说:U + 00C2字符在UTF-8中表示为0xc3 0x82,U + 00A3字符在UTF-8中表示为0xc2 0xa3。)
然后,在那之后的某个时间,同样的事情再次完成。使用一个字节的字符集读取这四个字节,每个字节被视为自己的字符,并且这四个字符中的每一个都被以UTF-8编码,产生8个字节:0xc3,0x83,0xc2,0x82,0xc3,0x82,0xc2,0xa3。 (当编码为UTF-8时,并非每个字符都转换为两个字节;恰好所有这些字符都是。)
这就是为什么当您使用ISO-8859-1字符集读取文件时,每个字节都会得到一个字符:
à ƒ  ‚ à ‚  £
c3 83 c2 82 c3 82 c2 a3
(从技术上讲,‚
实际上是U + 201A"单低-9引号,"但是许多每字符一个字节的Windows字体历史上在0x82位置都有该字符。)
所以,现在我们知道你的文件是怎么做到的,你怎么办呢?
首先,不要让它变得更糟。如果您可以控制正在编写文件的代码,请确保代码明确指定了读取和写入的字符集。 UTF-8几乎总是最佳选择,至少对于使用主要是西方字符的任何文件都是如此。
其次,如何修复文件?我担心,没有办法自动检测这种错误编码,但至少在这个文件的情况下,你可以对它进行三重解码。
如果文件不是很大,你可以将它全部读入内存:
byte[] bytes = Files.readAllBytes(Paths.get(csvDirectory, filename));
// First decoding: £ is represented as four characters
String content = new String(bytes, "UTF-8");
bytes = new byte[content.length()];
for (int i = content.length() - 1; i >= 0; i--) {
bytes[i] = (byte) content.charAt(i);
}
// Second decoding: £ is represented as two characters
content = new String(bytes, "UTF-8");
bytes = new byte[content.length()];
for (int i = content.length() - 1; i >= 0; i--) {
bytes[i] = (byte) content.charAt(i);
}
// Third decoding: £ is represented as one character
content = new String(bytes, "UTF-8");
br = new BufferedReader(new StringReader(content));
// ...
如果它是一个大文件,你会想要将每一行读作字节:
try (InputStream in = new BufferedInputStream(
Files.newInputStream(Paths.get(csvDirectory, filename)))) {
ByteBuffer lineBuffer = ByteBuffer.allocate(64 * 1024);
int b = 0;
while (b >= 0) {
lineBuffer.clear();
for (b = in.read();
b >= 0 && b != '\n' && b != '\r';
b = in.read()) {
lineBuffer.put((byte) b);
}
if (b == '\r') {
in.mark(1);
if (in.read() != '\n') {
in.reset();
}
}
lineBuffer.flip();
byte[] bytes = new byte[lineBuffer.limit()];
lineBuffer.get(bytes);
// First decoding: £ is represented as four characters
String parsedLine = new String(bytes, "UTF-8");
bytes = new byte[parsedLine.length()];
for (int i = parsedLine.length() - 1; i >= 0; i--) {
bytes[i] = (byte) parsedLine.charAt(i);
}
// Second decoding: £ is represented as two characters
parsedLine = new String(bytes, "UTF-8");
bytes = new byte[parsedLine.length()];
for (int i = parsedLine.length() - 1; i >= 0; i--) {
bytes[i] = (byte) parsedLine.charAt(i);
}
// Third decoding: £ is represented as one character
parsedLine = new String(bytes, "UTF-8");
// ...
}
}
答案 1 :(得分:2)
似乎是编码问题。找出您的文件编码的字符集。假设编码是UTF-8,你可以做这样的事情
<script>
import DatatableHeader from './DatatableHeader.vue';
export default {
data: {
columns: [{'heading': 'Column 1'}, {'heading': 'Column 2'}]
},
components: {
'datatableheader' : DatatableHeader,
}
}
</script>
这应该可以解决您的问题