📄 importreaddata.java
字号:
/* Derby - Class org.apache.derby.impl.load.ImportReadData Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed 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.derby.impl.load;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.FileInputStream;import java.io.IOException;import java.net.MalformedURLException;import java.net.URL;import org.apache.derby.iapi.services.sanity.SanityManager;final class ImportReadData implements java.security.PrivilegedExceptionAction { //Read data from this file private String inputFileName; private int[] columnWidths; private int rowWidth; private char[] tempString; private int numberOfCharsReadSoFar; //temporary variables private BufferedReader bufferedReader; //temporary variable which holds each token as we are building it. private static final int START_SIZE = 10240; private char[] currentToken = new char[START_SIZE]; private int currentTokenMaxSize = START_SIZE; //This tells whether to look for a matching stop pattern boolean foundStartDelimiter; int totalCharsSoFar; //following is used to ignore whitespaces in the front int positionOfNonWhiteSpaceCharInFront; //following is used to ignore whitespaces in the back int positionOfNonWhiteSpaceCharInBack; int lineNumber; int fieldStartDelimiterIndex; int fieldStopDelimiterIndex; int stopDelimiterPosition; boolean foundStartAndStopDelimiters; //in the constructor we open the stream only if it's delimited file to find out //number of columns. In case of fixed, we know that already from the control file. //then we close the stream. Now the stream is reopened when the first record is //read from the file(ie when the first time next is issued. This was done for the //bug 1032 filed by Dan boolean streamOpenForReading; static final int DEFAULT_FORMAT_CODE = 0; static final int ASCII_FIXED_FORMAT_CODE = 1; private int formatCode = DEFAULT_FORMAT_CODE; private boolean hasColumnDefinition; private char recordSeparatorChar0; private char fieldSeparatorChar0; private boolean recordSepStartNotWhite = true; private boolean fieldSepStartNotWhite = true; //get properties infr from following protected ControlInfo controlFileReader; //Read first row to find out how many columns make up a row and put it in //the following variable protected int numberOfColumns; // the types of the columns that we are about to read protected String [] columnTypes; //Read control file properties and write it in here protected char[] fieldSeparator; protected int fieldSeparatorLength; protected char[] recordSeparator; protected int recordSeparatorLength; protected String nullString; protected String columnDefinition; protected String format; protected String dataCodeset; protected char[] fieldStartDelimiter; protected int fieldStartDelimiterLength; protected char[] fieldStopDelimiter; protected int fieldStopDelimiterLength; protected boolean hasDelimiterAtEnd; //load the control file properties info locally, since we need to refer to them //all the time while looking for tokens private void loadPropertiesInfo() throws Exception { fieldSeparator = controlFileReader.getFieldSeparator().toCharArray(); fieldSeparatorLength = fieldSeparator.length; recordSeparator = controlFileReader.getRecordSeparator().toCharArray(); recordSeparatorLength = recordSeparator.length; nullString = controlFileReader.getNullString(); columnDefinition = controlFileReader.getColumnDefinition(); format = controlFileReader.getFormat(); dataCodeset = controlFileReader.getDataCodeset(); fieldStartDelimiter = controlFileReader.getFieldStartDelimiter().toCharArray(); fieldStartDelimiterLength = fieldStartDelimiter.length; fieldStopDelimiter = controlFileReader.getFieldEndDelimiter().toCharArray(); fieldStopDelimiterLength = fieldStopDelimiter.length; hasDelimiterAtEnd = controlFileReader.getHasDelimiterAtEnd(); // when record or field separators start with typical white space, // we can't ignore it around values in the import file. So set up // a boolean so we don't keep re-testing for it. if (recordSeparatorLength >0) { recordSeparatorChar0=recordSeparator[0]; recordSepStartNotWhite = (Character.isWhitespace(recordSeparatorChar0)==false); } if (fieldSeparatorLength >0) { fieldSeparatorChar0=fieldSeparator[0]; fieldSepStartNotWhite = (Character.isWhitespace(fieldSeparatorChar0)==false); } } //inputFileName: File to read data from //controlFileReader: File used to interpret data in the inputFileName ImportReadData(String inputFileName, ControlInfo controlFileReader) throws Exception { this.inputFileName = inputFileName; this.controlFileReader = controlFileReader; //load the control file properties info locally, since we need to refer to //them all the time while looking for tokens loadPropertiesInfo(); //read the first row to find how many columns make a row and then save that //column information for further use loadMetaData(); } //just a getter returning number of columns for a row in the data file int getNumberOfColumns() { return numberOfColumns; } /**if columndefinition is true, ignore first row. The way to do that is to just * look for the record separator * @exception Exception if there is an error */ protected void ignoreFirstRow() throws Exception { readNextToken(recordSeparator, 0, recordSeparatorLength, true); } /** load the column types from the meta data line to be analyzed * later in the constructor of the ImportResultSetMetaData. */ protected void loadColumnTypes() throws Exception { int idx; String [] metaDataArray; // start by counting the number of columns that we have at the // meta data line findNumberOfColumnsInARow(); // reopen the file to the start of the file to read the actual column types data closeStream(); openFile(); // make room for the meta data metaDataArray=new String [numberOfColumns]; // read the meta data line line - meta data is always in a delimited format readNextDelimitedRow(metaDataArray); // allocate space for the columnTypes meta data // since the meta data line contains a combination of column name and // column type for every column we actually have only half the number of // columns that was counted. columnTypes=new String[numberOfColumns/2]; for(idx=0 ; idx<numberOfColumns ; idx=idx+2) { columnTypes[idx/2]=metaDataArray[idx+1]; } // reopen to the start of the file so the rest of the program will // work as expected closeStream(); openFile(); // init the numberOfColumns variable since it is // being accumulate by the findNumberOfColumnsInARow method numberOfColumns=0; } private void openFile() throws Exception { try { java.security.AccessController.doPrivileged(this); } catch (java.security.PrivilegedActionException pae) { throw pae.getException(); } } public final Object run() throws Exception { realOpenFile(); return null; } //open the input data file for reading private void realOpenFile() throws Exception { InputStream inputStream; try { try { URL url = new URL(inputFileName); if (url.getProtocol().equals("file")) { //this means it's a file url inputFileName = url.getFile(); //seems like you can't do openstream on file throw new MalformedURLException(); //so, get the filename from url and do it ususal way } inputStream = url.openStream(); } catch (MalformedURLException ex) { inputStream = new FileInputStream(inputFileName); } } catch (FileNotFoundException ex) { throw LoadError.dataFileNotFound(inputFileName); } catch (SecurityException se) { java.sql.SQLException sqle = LoadError.dataFileNotFound(inputFileName); sqle.setNextException(new java.sql.SQLException("XJ001", se.getMessage(), 0)); throw sqle; } java.io.Reader rd = dataCodeset == null ? new InputStreamReader(inputStream) : new InputStreamReader(inputStream, dataCodeset); bufferedReader = new BufferedReader(rd, 32*1024); streamOpenForReading = true; } //read the first data row to find how many columns make a row and then save that //column information for future use private void loadMetaData() throws Exception { //open the input data file for reading the metadata information openFile(); // if column definition is true, ignore the first row since that's not // really the data do uppercase because the ui shows the values as True // and False if (columnDefinition.toUpperCase(java.util.Locale.ENGLISH).equals(ControlInfo.INTERNAL_TRUE.toUpperCase(java.util.Locale.ENGLISH))) { hasColumnDefinition = true; ignoreFirstRow(); } if (formatCode == DEFAULT_FORMAT_CODE) { findNumberOfColumnsInARow(); } closeStream(); } /**close the input data file * @exception Exception if there is an error */ void closeStream() throws Exception { if (streamOpenForReading) { bufferedReader.close(); streamOpenForReading = false; } } //actually looks at the data file to find how many columns make up a row int findNumberOfColumnsInARow() throws Exception { // init the number of columns to 1 - no such thing as a table // without columns numberOfColumns=1; while (! readTokensUntilEndOfRecord() ) { numberOfColumns++; } //--numberOfColumns; //what shall we do if there is delimeter after the last column? //reducing the number of columns seems to work fine. //this is necessary to be able to read delimited files that have a delimeter //at the end of a row. if (hasDelimiterAtEnd){ --numberOfColumns; } // a special check - if the imported file is empty then // set the number of columns to 0 if (numberOfCharsReadSoFar==0) { numberOfColumns=0; } return numberOfColumns; } //keep track of white spaces in the front. We use positionOfNonWhiteSpaceCharInFront for //that. It has the count of number of white spaces found so far before any non-white char //in the token. //Look for whitespace only if field start delimiter is not found yet. Any white spaces //within the start and stop delimiters are ignored. //Also if one of the white space chars is same as recordSeparator or fieldSeparator then //disregard it. private void checkForWhiteSpaceInFront() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -