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给出的答案/解释。