You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2014/01/01 20:59:43 UTC

svn commit: r1554669 - in /jena/trunk/jena-arq/src: main/java/org/apache/jena/atlas/io/BufferingWriter.java test/java/org/apache/jena/atlas/io/TS_IO.java test/java/org/apache/jena/atlas/io/TestBufferingWriter.java

Author: andy
Date: Wed Jan  1 19:59:42 2014
New Revision: 1554669

URL: http://svn.apache.org/r1554669
Log:
BufferingWriter.
Like java.io.BufferedWriter but without the hidden synchronization costs of that class
which can show up for large numbers of small outputs, e.g. outputing single character.

Added:
    jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
    jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
Modified:
    jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TS_IO.java

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java?rev=1554669&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java Wed Jan  1 19:59:42 2014
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.atlas.io ;
+
+import java.io.IOException ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.io.IO ;
+
+/**
+ * A buffering writer. Like BufferedWriter but with no synchronization. A
+ * "synchronized" per character can be expensive.
+ * <p>
+ * The standard java.io classes have hidden synchronization so in some very
+ * critical situations, this can be expensive.
+ * </p>
+ * This class is not thread safe.
+ */
+
+public final class BufferingWriter extends Writer {
+    // Default sizes
+    private static final int SIZE      = 8 * 1024 ;      // Unit size in bytes.
+    private static final int BLOB_SIZE = SIZE / 2 ;      // Large object size,
+                                                          // worse case, bytes
+    // Sizes for this instance
+    private final int        blockSize ;
+    private final int        blobSize ;
+
+    private char[]           buffer    = new char[SIZE] ;
+    private int              idx       = 0 ;
+    // *** AWriter?
+    private Writer           out ;
+
+    /** Create a buffering writer */
+    public BufferingWriter(Writer dest) {
+        this(dest, SIZE, BLOB_SIZE) ;
+    }
+
+    /** Create a buffering writer */
+    public BufferingWriter(Writer dest, int size, int blobSize) {
+        this.out = dest ;
+        this.blockSize = size ;
+        this.blobSize = blobSize ;
+    }
+
+    /**
+     * Output a string
+     * @param string Characters
+     */
+    public void output(String string) {
+        output(string, 0, string.length()) ;
+    }
+    
+    /**
+     * Output a string
+     * 
+     * @param string Characters
+     * @param off    Starting point in the string
+     * @param length Length
+     */
+    public void output(String string, int off, int length) {
+        boolean largeBlob = (length > blobSize) ;
+
+        // There is no space or too big
+        if ( largeBlob || (blockSize - idx) < length )
+            flushBuffer() ;
+        // If too big, do directly.
+        if ( largeBlob /* too big */) {
+            try { out.write(string, off, length) ; }
+            catch (IOException ex) { IO.exception(ex) ; }
+            return ;
+        }
+        int n = string.length() ;
+        string.getChars(off, (n + off), buffer, idx) ;
+        idx += n ;
+    }
+
+    /** Output an array of characters */
+    public void output(char chars[]) {
+        output(chars, 0, chars.length) ;
+    }
+
+    /**
+     * Output an array of characters
+     * 
+     * @param chars Characters
+     * @param start Start
+     * @param length Length
+     */
+    public void output(char chars[], int start, int length) {
+        boolean largeBlob = (length > blobSize) ;
+
+        // There is no space or too big
+        if ( largeBlob || (blockSize - idx) < length )
+            flushBuffer() ;
+        // If too big, do directly.
+        if ( largeBlob /* too big */) {
+            try { out.write(chars) ; }
+            catch (IOException ex) { IO.exception(ex) ; }
+            return ;
+        }
+        System.arraycopy(chars, start, buffer, idx, length) ;
+        idx += length ;
+    }
+
+    /** Output a single character */
+    public void output(char ch) {
+        if ( blockSize == idx )
+            flushBuffer() ;
+        buffer[idx++] = ch ;
+    }
+
+    private void flushBuffer() {
+        if ( idx > 0 ) {
+            try { out.write(buffer, 0, idx) ; }
+            catch (IOException ex) { IO.exception(ex) ; }
+            idx = 0 ;
+        }
+
+    }
+    
+    // ---- Writer
+
+    @Override
+    public void close() {
+        flushBuffer() ;
+        IO.close(out) ;
+    }
+
+    @Override
+    public void flush() {
+        flushBuffer() ;
+        IO.flush(out) ;
+    }
+
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        output(cbuf, off, len) ;
+    }
+
+    @Override
+    public void write(char[] cbuf) throws IOException {
+        write(cbuf, 0, cbuf.length) ;
+    }
+
+    @Override
+    public void write(String string, int off, int len) throws IOException {
+        output(string, off, len) ;
+    }
+
+    @Override
+    public void write(String string) throws IOException {
+        output(string, 0, string.length()) ;
+    }
+
+    @Override
+    public void write(int ch) throws IOException {
+        output((char)ch) ;
+    }
+}

Modified: jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TS_IO.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TS_IO.java?rev=1554669&r1=1554668&r2=1554669&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TS_IO.java (original)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TS_IO.java Wed Jan  1 19:59:42 2014
@@ -33,8 +33,9 @@ import org.junit.runners.Suite ;
     , TestPeekReaderSource.class
     , TestPeekReaderCharSequence.class
     , TestPeekInputStreamSource.class
-    //, TestPeekInputStreamBytes.class
-    
+
+    // Writers
+    , TestBufferingWriter.class
     // Other
     , TestPrintUtils.class
 } )

Added: jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java?rev=1554669&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java (added)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java Wed Jan  1 19:59:42 2014
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.atlas.io ;
+
+import java.io.StringWriter ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestBufferingWriter extends BaseTest {
+    StringWriter    sw = null ;
+    BufferingWriter w  = null ;
+
+    public void create(int size, int blobSize) {
+        sw = new StringWriter() ;
+        w = new BufferingWriter(sw, size, blobSize) ;
+    }
+
+    public String string() {
+        return sw.toString() ;
+    }
+
+    @Test
+    public void write_01() {
+        create(10, 5) ;
+        w.output("x") ;
+        w.flush() ;
+        String x = string() ;
+        assertEquals("x", x) ;
+    }
+
+    @Test
+    public void write_02() {
+        create(10, 5) ;
+        w.output("foofoo") ; // Large object
+        w.flush() ;
+        String x = string() ;
+        assertEquals("foofoo", x) ;
+    }
+
+    @Test
+    public void write_03() {
+        create(10, 8) ;
+        w.output("a") ;
+        w.output("b") ;
+        w.output("c") ;
+        w.flush() ;
+        String x = string() ;
+        assertEquals("abc", x) ;
+    }
+
+    @Test
+    public void write_04() {
+        create(10, 8) ;
+        w.output("abcdefghijklmnopqrstuvwxyz") ;
+        w.output("XYZ") ;
+        w.flush() ;
+        String x = string() ;
+        assertEquals("abcdefghijklmnopqrstuvwxyzXYZ", x) ;
+    }
+
+    @Test
+    public void write_05() {
+        create(10, 8) ;
+        w.output("") ;
+        w.flush() ;
+        String x = string() ;
+        assertEquals("", x) ;
+    }
+
+    @Test
+    public void write_06() {
+        // Test closing the stream without flushing (the flush should be done
+        // implicitly)
+        create(100, 50) ;
+        w.output("test") ;
+        w.close() ;
+        String x = string() ;
+        assertEquals("test", x) ;
+    }
+}