You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2013/04/17 02:59:43 UTC

svn commit: r1468703 - in /commons/proper/io/trunk/src: changes/changes.xml main/java/org/apache/commons/io/input/Tailer.java test/java/org/apache/commons/io/input/TailerTest.java

Author: sebb
Date: Wed Apr 17 00:59:42 2013
New Revision: 1468703

URL: http://svn.apache.org/r1468703
Log:
IO-354 Commons IO Tailer does not respect UTF-8 Charset

Modified:
    commons/proper/io/trunk/src/changes/changes.xml
    commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java
    commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java

Modified: commons/proper/io/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1468703&r1=1468702&r2=1468703&view=diff
==============================================================================
--- commons/proper/io/trunk/src/changes/changes.xml (original)
+++ commons/proper/io/trunk/src/changes/changes.xml Wed Apr 17 00:59:42 2013
@@ -47,6 +47,9 @@ The <action> type attribute can be add,u
   <body>
     <!-- The release date is the date RC is cut -->
     <release version="2.5" date="2013-??-??" description="New features and bug fixes.">    
+      <action issue="IO-354" dev="sebb" type="fix">
+        Commons IO Tailer does not respect UTF-8 Charset.
+      </action>            
       <action issue="IO-323" dev="sebb" type="fix">
         What should happen in FileUtils.sizeOf[Directory] when an overflow takes place?
         Added Javadoc. 

Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java?rev=1468703&r1=1468702&r2=1468703&view=diff
==============================================================================
--- commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java (original)
+++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java Wed Apr 17 00:59:42 2013
@@ -16,10 +16,12 @@
  */
 package org.apache.commons.io.input;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.nio.charset.Charset;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
@@ -444,11 +446,11 @@ public class Tailer implements Runnable 
      * @throws java.io.IOException if an I/O error occurs.
      */
     private long readLines(final RandomAccessFile reader) throws IOException {
-        final StringBuilder sb = new StringBuilder();
-
+        // Make explicit that the default charset is being used here
+        Charset cset = Charset.defaultCharset();
+        ByteArrayOutputStream lineBuf = new ByteArrayOutputStream(64);
         long pos = reader.getFilePointer();
         long rePos = pos; // position to re-read
-
         int num;
         boolean seenCR = false;
         while (getRun() && ((num = reader.read(inbuf)) != -1)) {
@@ -457,30 +459,29 @@ public class Tailer implements Runnable 
                 switch (ch) {
                 case '\n':
                     seenCR = false; // swallow CR before LF
-                    listener.handle(sb.toString());
-                    sb.setLength(0);
+                    listener.handle(new String(lineBuf.toByteArray(), cset));
+                    lineBuf.reset();
                     rePos = pos + i + 1;
                     break;
                 case '\r':
                     if (seenCR) {
-                        sb.append('\r');
+                        lineBuf.write('\r');
                     }
                     seenCR = true;
                     break;
                 default:
                     if (seenCR) {
                         seenCR = false; // swallow final CR
-                        listener.handle(sb.toString());
-                        sb.setLength(0);
+                        listener.handle(new String(lineBuf.toByteArray(), cset));
+                        lineBuf.reset(); 
                         rePos = pos + i + 1;
                     }
-                    sb.append((char) ch); // add character, not its ascii value
+                    lineBuf.write(ch);
                 }
             }
-
             pos = reader.getFilePointer();
         }
-
+        IOUtils.closeQuietly(lineBuf); // not strictly necessary
         reader.seek(rePos); // Ensure we can re-read if necessary
         return rePos;
     }

Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java?rev=1468703&r1=1468702&r2=1468703&view=diff
==============================================================================
--- commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java (original)
+++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java Wed Apr 17 00:59:42 2013
@@ -16,10 +16,13 @@
  */
 package org.apache.commons.io.input;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.RandomAccessFile;
 import java.io.Writer;
 import java.util.ArrayList;
@@ -105,6 +108,42 @@ public class TailerTest extends FileBase
         listener.clear();
     }
 
+    public void testMultiByteBreak() throws Exception {
+        final long delay = 50;
+        final File origin = new File(this.getClass().getResource("/test-file-utf8.bin").toURI());
+        final File file = new File(getTestDirectory(), "testMultiByteBreak.txt");
+        createFile(file, 0);
+        final TestTailerListener listener = new TestTailerListener();
+        final String osname = System.getProperty("os.name");
+        final boolean isWindows = osname.startsWith("Windows");
+        tailer = new Tailer(file, listener, delay, false, isWindows);
+        final Thread thread = new Thread(tailer);
+        thread.start();
+		
+        
+        BufferedReader reader = null;
+        try{
+        	List<String> lines = new ArrayList<String>();
+        	reader = new BufferedReader(new InputStreamReader(new FileInputStream(origin)));
+        	String line = null;
+        	while((line = reader.readLine()) != null){
+        		write(file, line);
+        		lines.add(line);
+        	}
+
+           final long testDelayMillis = delay * 10;
+           Thread.sleep(testDelayMillis);
+           List<String> tailerlines = listener.getLines();
+           assertEquals("line count",lines.size(),tailerlines.size());
+           for(int i = 0,len = lines.size();i<len;i++){
+        	   assertEquals("line "+i, lines.get(i), tailerlines.get(i));
+           }
+        }finally{
+        	tailer.stop();
+        	IOUtils.closeQuietly(reader);
+        }
+    }
+
     public void testTailerEof() throws Exception {
         // Create & start the Tailer
         final long delay = 50;