2014-09-19 81 views
0

我有一個簡單的方法,它讀取文件,根據條件修改一些行,然後將修改後的字符串寫回同一個文件。大綱如下:番石榴的`文件#寫入`不寫最後一個空行?

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()); 
} 

輸入文件有一個空的最後一行,我希望輸出文件保留。但是,儘管modifiedLines.add("")然後加入\n,輸出文件沒有最後一個空行。據我所知,番石榴的Files#write不做任何修剪,那麼爲什麼會發生這種情況呢?

我知道還有很多其他寫作方式最後一個空行。但我想知道這個方法出了什麼問題。

+0

爲什麼downvote?我的問題對某些人來說可能看起來很愚蠢,但我相信很多人都可以從(i)我的錯誤,更重要的是,(ii)@maaartinus給出的回答/解釋中受益。 – 2014-09-27 02:06:52

回答

2

這很簡單:加入者加入,你得到一個字符串而不終止'\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) 

你可以使用一個功能追加新行,而不是木匠,但是這是較長(至少與Java < 8)和慢因外部字符串創建。

+1

所有這些年來,我一直認爲添加'\ n'會在最後給我一個可見的空行。在面對一些最簡單的事實之前,可以寫多少行代碼是很奇怪的! – 2014-09-20 00:30:46

+0

我不明白爲什麼這是正確的答案。在你的例子中,你有兩條空行'\ n (空)\ n (空)' – rds 2014-09-20 00:35:07

+0

@rds不可以。\ n'屬於上一行。 – maaartinus 2014-09-20 00:42:46

0

對不起,一切都適合我。這些測試都通過與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) 
+0

你的測試很好,但沒有。你的文本中只有兩個'\ n',這意味着兩個終止的行,沒有更多。通常的理解是EOF中的空行看起來像'\ n \ n'(例如,整個文本將是'a \ nb \ n \ n')。 – maaartinus 2014-09-20 00:45:12

+0

是的,我想我們沒有以同樣的方式定義「空行」。對我而言,「abc」是一行文本文件,「abc \ n」是一個帶有兩行(一個帶有文本,一個空)的文本文件,「abc \ n \ n」是帶有兩個空行的文本文件。順便說一句,這就是TextWrangler,TextMate和IntelliJ如何計數行數。 – rds 2014-09-20 09:44:26

+0

你認爲'\ n'是一個行分隔符,這是有道理的。由於我使用的git在最後一行中抱怨缺少'\ n',我堅持其定義。我試圖使用'/ usr/bin/wc -l'對行進行計數,並聲稱'a \ nb'是單行。 ;)另一種可能性。 – maaartinus 2014-09-20 15:57:56