Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing只读取AbstractDocument.Content的第一个字符。我做错了什么?_Java_Swing_Document_Large Files - Fatal编程技术网

Java Swing只读取AbstractDocument.Content的第一个字符。我做错了什么?

Java Swing只读取AbstractDocument.Content的第一个字符。我做错了什么?,java,swing,document,large-files,Java,Swing,Document,Large Files,我的作品中有一个功能,我应该显示一个巨大的文本文件。所以我想,一旦文件超过一定大小,我会尝试在磁盘上映射文件的内存 文本至少是不可变的,这应该比编写支持相同大小的完整编辑器更容易 以下是我目前掌握的情况: public class CharBufferContent implements AbstractDocument.Content { private final CharBuffer charBuffer; private final int length; pu

我的作品中有一个功能,我应该显示一个巨大的文本文件。所以我想,一旦文件超过一定大小,我会尝试在磁盘上映射文件的内存

文本至少是不可变的,这应该比编写支持相同大小的完整编辑器更容易

以下是我目前掌握的情况:

public class CharBufferContent implements AbstractDocument.Content {
    private final CharBuffer charBuffer;
    private final int length;

    public CharBufferContent(CharBuffer charBuffer) {
        this.charBuffer = charBuffer;
        length = charBuffer.length();
    }

    public Position createPosition(int offset) throws BadLocationException {
        return new ImmutablePosition(offset);
    }

    public int length() {
        return length;
    }

    public UndoableEdit insertString(int where, String string)
            throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    public UndoableEdit remove(int where, int nItems) throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    public String getString(int where, int length) throws BadLocationException {
        if (where < 0 || where + length > this.length) {
            throw new BadLocationException("Invalid range", this.length);
        }

        char[] out = new char[length];
        charBuffer.position(where);
        charBuffer.get(out);
        return new String(out);
    }

    public void getChars(int where, int length, Segment segment)
            throws BadLocationException {
        if (where < 0 || where + length > this.length) {
            throw new BadLocationException("Invalid range", this.length);
        }

        // This will be inefficient, but I'm just trying to get it working first.
        segment.array = new char[length];
        charBuffer.position(where);
        charBuffer.get(segment.array, 0, length);
        segment.offset = 0;
        segment.count = length;
    }

    private static class ImmutablePosition implements Position {
        private final int offset;

        private ImmutablePosition(int offset) {
            this.offset = offset;
        }

        @Override
        public int getOffset() {
            return offset;
        }
    }
}
当我运行它时,窗口显示“T”。在调试器中,我可以看到Swing只调用
length()
getChars()
。每次调用
getChars()
都有
where==0
length==1
。因此,它只有一个字符可以显示是有道理的,但是Swing调用我的代码并且只要求第一个字符似乎很奇怪,尽管我可以看到
length()
返回文本的完整长度

当我使用与实现相同的StringContent运行相同的测试时,
getChars()
,该测试将以文档的完整长度调用

这个API中没有太多看起来可能出错的地方,所以我很困惑


这里发生了什么?

我对文档API不太熟悉,但我的理解是,
AbstractDocument.Content
不需要预先配备自己的文本。AbstractDocument不知道在这种情况下该怎么办。如果您尝试使用StringContent,您将看到相同的问题:

content = new StringContent();
content.insertString(0, "some text");
final AbstractDocument document = new PlainDocument(content);
这仅显示前导的“s”。显然,AbstractDocument在文档末尾为插入符号建模了一个额外的有效位置,它希望其内容的长度为+1,其实际长度支持这一点,我相信这就是第一个字符确实出现的原因

如果在创建文档后调用
StringContent.insertString
,它似乎可以显示所有文本,但我认为这可能只是运气。如果以这种方式插入的字符串包含换行符,它将始终忽略这些换行符,因为它们不是按要求作为单独的文档元素建模的

我认为完成这项工作的唯一方法是直接实现文档,而不是AbstractDocument.Content。这是一个更复杂的界面,但它确实有效:

class CharBufferDocument implements Document {
    private final CharBuffer charBuffer;
    private final int length;
    private final int[] lineOffsets;

    public CharBufferDocument(CharBuffer charBuffer) {
        this.charBuffer = charBuffer;

        charBuffer.position(0);
        length = charBuffer.length();

        int[] lineOffsets = new int[] { 0 };
        int lineCount = 1;

        for (int i = 0; i < length; i++) {
            char c = charBuffer.get(i);
            if (c == '\n') {
                if (lineCount == lineOffsets.length) {
                    if (lineCount == Integer.MAX_VALUE) throw new OutOfMemoryError();
                    int newLength = (int)Math.min(lineCount * 2L, Integer.MAX_VALUE);
                    lineOffsets = Arrays.copyOf(lineOffsets, newLength);
                }
                lineOffsets[lineCount++] = i + 1;
            }
        }

        lineOffsets = Arrays.copyOf(lineOffsets, lineCount);
        this.lineOffsets = lineOffsets;
    }

    @Override
    public int getLength() {
        return length;
    }

    @Override
    public void addDocumentListener(DocumentListener listener) {}

    @Override
    public void removeDocumentListener(DocumentListener listener) {}

    @Override
    public void addUndoableEditListener(UndoableEditListener listener) {}

    @Override
    public void removeUndoableEditListener(UndoableEditListener listener) {}

    @Override
    public void putProperty(Object key, Object value) {}

    @Override
    public Object getProperty(Object key) {
        return null;
    }

    @Override
    public void remove(int offs, int len) throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    @Override
    public void insertString(int offset, String str, AttributeSet a)
            throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    @Override
    public String getText(int offset, int length) throws BadLocationException {
        char[] out = new char[length];
        charBuffer.position(offset);
        charBuffer.get(out);
        return new String(out);
    }

    @Override
    public void getText(int offset, int length, Segment segment) throws BadLocationException {
        segment.array = new char[length];
        charBuffer.position(offset);
        charBuffer.get(segment.array);
        segment.offset = 0;
        segment.count = length;
    }

    @Override
    public Position getStartPosition() {
        return createPosition(0);
    }

    @Override
    public Position getEndPosition() {
        return createPosition(getLength());
    }

    @Override
    public Position createPosition(int offset) {
        return new ImmutablePosition(offset);
    }

    private final Element rootElement = new Element() {
        @Override
        public Document getDocument() {
            return CharBufferDocument.this;
        }

        @Override
        public Element getParentElement() {
            return null;
        }

        @Override
        public String getName() {
            return "root";
        }

        @Override
        public AttributeSet getAttributes() {
            return null;
        }

        @Override
        public int getStartOffset() {
            return 0;
        }

        @Override
        public int getEndOffset() {
            return getLength();
        }

        @Override
        public int getElementIndex(int offset) {
            // binary search for the line that contains offset
            int low = 0;
            int high = lineOffsets.length - 1;

            while (low <= high) {
                int mid = (low + high) >>> 1;
                int midLineStart = lineOffsets[mid];
                int midLineEnd = (mid + 1 < lineOffsets.length) ? (lineOffsets[mid + 1] - 1) : getLength();

                if (offset < midLineStart) {
                    high = mid - 1;
                } else if (offset > midLineEnd) {
                    low = mid + 1;
                } else {
                    return mid;
                }
            }
            return 0;
        }

        @Override
        public int getElementCount() {
            return lineOffsets.length;
        }

        @Override
        public Element getElement(int index) {
            return createLineElement(
                lineOffsets[index],
                (index + 1 < lineOffsets.length) ? (lineOffsets[index + 1] - 1) : getLength()
            );
        }

        @Override
        public boolean isLeaf() {
            return false;
        }
    };

    private Element createLineElement(final int start, final int end) {
        return new Element() {
            @Override
            public Document getDocument() {
                return CharBufferDocument.this;
            }

            @Override
            public Element getParentElement() {
                return CharBufferDocument.this.getDefaultRootElement();
            }

            @Override
            public String getName() {
                return "line"; // XXX: Does the name matter?
            }

            @Override
            public AttributeSet getAttributes() {
                return null;
            }

            @Override
            public int getStartOffset() {
                return start;
            }

            @Override
            public int getEndOffset() {
                return end;
            }

            @Override
            public int getElementIndex(int offset) {
                return -1;
            }

            @Override
            public int getElementCount() {
                return 0;
            }

            @Override
            public Element getElement(int index) {
                return null;
            }

            @Override
            public boolean isLeaf() {
                return true;
            }
        };
    }

    @Override
    public Element getDefaultRootElement() {
        return rootElement;
    }

    @Override
    public Element[] getRootElements() {
        return new Element[] { getDefaultRootElement() };
    }

    @Override
    public void render(Runnable r) {
        r.run();
    }

    private static class ImmutablePosition implements Position {
        private final int offset;

        private ImmutablePosition(int offset) {
            this.offset = offset;
        }

        @Override
        public int getOffset() {
            return offset;
        }
    }
}
类CharBufferDocument实现文档{
专用最终字符缓冲区字符缓冲区;
私有最终整数长度;
专用最终int[]行偏移量;
公共CharBufferDocument(CharBuffer CharBuffer){
this.charBuffer=charBuffer;
位置(0);
length=charBuffer.length();
int[]lineoffset=新的int[]{0};
int lineCount=1;
for(int i=0;i>1;
class CharBufferDocument implements Document {
    private final CharBuffer charBuffer;
    private final int length;
    private final int[] lineOffsets;

    public CharBufferDocument(CharBuffer charBuffer) {
        this.charBuffer = charBuffer;

        charBuffer.position(0);
        length = charBuffer.length();

        int[] lineOffsets = new int[] { 0 };
        int lineCount = 1;

        for (int i = 0; i < length; i++) {
            char c = charBuffer.get(i);
            if (c == '\n') {
                if (lineCount == lineOffsets.length) {
                    if (lineCount == Integer.MAX_VALUE) throw new OutOfMemoryError();
                    int newLength = (int)Math.min(lineCount * 2L, Integer.MAX_VALUE);
                    lineOffsets = Arrays.copyOf(lineOffsets, newLength);
                }
                lineOffsets[lineCount++] = i + 1;
            }
        }

        lineOffsets = Arrays.copyOf(lineOffsets, lineCount);
        this.lineOffsets = lineOffsets;
    }

    @Override
    public int getLength() {
        return length;
    }

    @Override
    public void addDocumentListener(DocumentListener listener) {}

    @Override
    public void removeDocumentListener(DocumentListener listener) {}

    @Override
    public void addUndoableEditListener(UndoableEditListener listener) {}

    @Override
    public void removeUndoableEditListener(UndoableEditListener listener) {}

    @Override
    public void putProperty(Object key, Object value) {}

    @Override
    public Object getProperty(Object key) {
        return null;
    }

    @Override
    public void remove(int offs, int len) throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    @Override
    public void insertString(int offset, String str, AttributeSet a)
            throws BadLocationException {
        throw new UnsupportedOperationException("Document is immutable");
    }

    @Override
    public String getText(int offset, int length) throws BadLocationException {
        char[] out = new char[length];
        charBuffer.position(offset);
        charBuffer.get(out);
        return new String(out);
    }

    @Override
    public void getText(int offset, int length, Segment segment) throws BadLocationException {
        segment.array = new char[length];
        charBuffer.position(offset);
        charBuffer.get(segment.array);
        segment.offset = 0;
        segment.count = length;
    }

    @Override
    public Position getStartPosition() {
        return createPosition(0);
    }

    @Override
    public Position getEndPosition() {
        return createPosition(getLength());
    }

    @Override
    public Position createPosition(int offset) {
        return new ImmutablePosition(offset);
    }

    private final Element rootElement = new Element() {
        @Override
        public Document getDocument() {
            return CharBufferDocument.this;
        }

        @Override
        public Element getParentElement() {
            return null;
        }

        @Override
        public String getName() {
            return "root";
        }

        @Override
        public AttributeSet getAttributes() {
            return null;
        }

        @Override
        public int getStartOffset() {
            return 0;
        }

        @Override
        public int getEndOffset() {
            return getLength();
        }

        @Override
        public int getElementIndex(int offset) {
            // binary search for the line that contains offset
            int low = 0;
            int high = lineOffsets.length - 1;

            while (low <= high) {
                int mid = (low + high) >>> 1;
                int midLineStart = lineOffsets[mid];
                int midLineEnd = (mid + 1 < lineOffsets.length) ? (lineOffsets[mid + 1] - 1) : getLength();

                if (offset < midLineStart) {
                    high = mid - 1;
                } else if (offset > midLineEnd) {
                    low = mid + 1;
                } else {
                    return mid;
                }
            }
            return 0;
        }

        @Override
        public int getElementCount() {
            return lineOffsets.length;
        }

        @Override
        public Element getElement(int index) {
            return createLineElement(
                lineOffsets[index],
                (index + 1 < lineOffsets.length) ? (lineOffsets[index + 1] - 1) : getLength()
            );
        }

        @Override
        public boolean isLeaf() {
            return false;
        }
    };

    private Element createLineElement(final int start, final int end) {
        return new Element() {
            @Override
            public Document getDocument() {
                return CharBufferDocument.this;
            }

            @Override
            public Element getParentElement() {
                return CharBufferDocument.this.getDefaultRootElement();
            }

            @Override
            public String getName() {
                return "line"; // XXX: Does the name matter?
            }

            @Override
            public AttributeSet getAttributes() {
                return null;
            }

            @Override
            public int getStartOffset() {
                return start;
            }

            @Override
            public int getEndOffset() {
                return end;
            }

            @Override
            public int getElementIndex(int offset) {
                return -1;
            }

            @Override
            public int getElementCount() {
                return 0;
            }

            @Override
            public Element getElement(int index) {
                return null;
            }

            @Override
            public boolean isLeaf() {
                return true;
            }
        };
    }

    @Override
    public Element getDefaultRootElement() {
        return rootElement;
    }

    @Override
    public Element[] getRootElements() {
        return new Element[] { getDefaultRootElement() };
    }

    @Override
    public void render(Runnable r) {
        r.run();
    }

    private static class ImmutablePosition implements Position {
        private final int offset;

        private ImmutablePosition(int offset) {
            this.offset = offset;
        }

        @Override
        public int getOffset() {
            return offset;
        }
    }
}