Java 番石榴';s`Files#write`not';不写最后一行空行吗?
我有一个简单的方法,它读取一个文件,根据条件修改一些行,然后将修改后的字符串写回同一个文件。大纲如下:Java 番石榴';s`Files#write`not';不写最后一行空行吗?,java,file-io,guava,Java,File Io,Guava,我有一个简单的方法,它读取一个文件,根据条件修改一些行,然后将修改后的字符串写回同一个文件。大纲如下: import com.google.common.base.Joiner; import com.google.common.io.Files; import static java.nio.charset.Charset.defaultCharset; static final DIR = ; String enforceVerbTag(String inputfilename) {
import com.google.common.base.Joiner;
import com.google.common.io.Files;
import static java.nio.charset.Charset.defaultCharset;
static final DIR = ;
String enforceVerbTag(String inputfilename) {
String predictedTags = Files.toString(new File(DIR, inputfilename),
defaultCharset());
String[] lines = predictedTags.split("\\r?\\n");
List<String> modifiedLines = new ArrayList<>();
for (String line : lines) {
String[] fields = line.split("\\t");
if (mycondition)
fields[1] = "VB";
String modifiedLine = Joiner.on('\t').join(fields);
modifiedLines.add(modifiedLine);
}
modifiedLines.add("");
Files.write(Joiner.on('\n').join(modifiedLines),
new File(DIR, inputfilename),
defaultCharset());
}
import com.google.common.base.Joiner;
导入com.google.common.io.Files;
导入静态java.nio.charset.charset.defaultCharset;
静态最终目录=;
字符串enforceVerbTag(字符串输入文件名){
String predictedTags=Files.toString(新文件(DIR,inputfilename),
defaultCharset());
字符串[]行=predictedTags.split(\\r?\\n”);
List modifiedLines=新建ArrayList();
用于(字符串行:行){
字符串[]字段=行。拆分(\\t“);
if(霉菌病)
字段[1]=“VB”;
字符串modifiedLine=Joiner.on('\t').join(字段);
修改行。添加(修改行);
}
修改行。添加(“”);
file.write(Joiner.on('\n').join(modifiedLines),
新文件(目录,输入文件名),
defaultCharset());
}
输入文件的最后一行为空,我希望输出文件保留该行。但是,尽管修改了lines.add(“”
,然后在\n
上加入,输出文件没有最后一行空行。据我所知,番石榴的文件#write
不会做任何修剪,那么为什么会发生这种情况呢
我知道写最后一行空行还有很多其他的方法。但是我想知道这个方法出了什么问题。很简单:joiner加入,你得到一个字符串而不终止
'\n'
first \n
second \n
third (no \n)
然后添加一个空字符串,它只会终止最后一行:
first \n
second \n
third \n
(nothing) (no \n)
您必须添加另一个“
以获得空行
first \n
second \n
third \n
(nothing) \n
(nothing) (no \n)
您可以使用附加换行符的函数来代替joiner,但这会更长(至少在Java<8中是这样),而且由于创建了无关的字符串,速度会更慢。对不起,一切都适合我。这些测试通过JDK7和番石榴12.0.1
@RunWith(JUnit4.class)
public class GuavaTests {
@Test
public void testJoiner() {
assertEquals("a\nb", Joiner.on('\n').join(ImmutableList.of("a", "b")));
assertEquals("a\nb\n", Joiner.on('\n').join(ImmutableList.of("a", "b", "")));
}
public void testFilesWrite() throws IOException {
File f = new File("tests.txt");
final String content="a\nb\n";
Files.write(content, f, Charset.defaultCharset());
assertEquals(content.length(), f.length());
}
}
文本文件包含3行:
a
b
(empty)
这些年来,我一直认为添加一个
\n
会在末尾留下一条可见的空行。在面对一些最简单的事实之前,一个人能写多少行代码真是不可思议!我不明白为什么这是正确的答案。在您的示例中,您有两行空行\n(nothing)\n(nothing)
@rds No.\n
属于前一行。您的测试没有问题,但没有问题。您的文本中正好有两行\n
,这意味着两行终止,仅此而已。通常的理解是,EOF中的空行看起来像\n\n
(例如,整个文本将是a\nb\n\n
)。是的,我想我们对“空行”的定义不一样。对我来说,“abc”是一个只有一行的文本文件,“abc\n”是一个有两行的文本文件(一行有文本,一行空),“abc\n\n”是一个有两行空的文本文件。顺便说一下,这就是TextWrangler、TeMatle和IntLyj.计数行。你认为<代码> \n>代码>是行分隔符,这是有意义的。由于我使用的git抱怨最后一行缺少\n
,因此我坚持使用它的定义。我尝试使用/usr/bin/wc-l
来计算行数,它声称a\nb
是一行还有一种可能性,为什么要投否决票?我的问题在某些人看来可能很愚蠢,但我相信很多人可以从(I)我的错误中受益,更重要的是,(ii)由@maaartinus给出的答案/解释。