前面都说过了,还有点就是注意不同类型的值在CSV文件里面可能有不同的形式,有些有双引号,注意这点估计OK了
解决方案 »
- 新手问下:SWT登录界面切换
- 关于歌词同步
- 对象缓存 高手进
- 急!servlet编译通过,没有结果是什么原因?
- 请问JAVA跟C#比的优势是什么?主要是面向什么的开发啊?
- 关于继承和构造函数的问题
- 高分求一个简单的socket问题:Note:MySocketServer.java uses or overrides a deprecated API.
- 在java JFrame里面动态改变菜单怎么要手工调整一下窗体大小才能正确显示呢?
- 我做了一个application 来测试连接数据库,出现如下问题:
- 两个小问题。。。
- 字符串长度问题。
- 大家帮帮忙,看如何把image对象写入文件,存为一种具体的图象格式
import java.io.EOFException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;public class CSVReader
{
private static final boolean DEBUGGING = true; /**
* Constructor
*
* @param r input Reader source of CSV Fields to read.
*
* @param separator
* field separator character, usually ',' in North America,
* ';' in Europe and sometimes '\t' for tab.
* @param quote
* char to use to enclose fields containing a separator,
* usually '\"'
* @param allowMultiLineFields
* true if reader should allow
* quoted fields to span
* more than one line. Microsoft Excel
* sometimes generates files like this.
* @param trim true if reader should trim lead/trailing whitespace
* e.g. blanks, Cr, Lf. Tab off fields.
*/
public CSVReader ( Reader r,
char separator,
char quote,
boolean allowMultiLineFields,
boolean trim
)
{
/* convert Reader to BufferedReader if necessary */
if ( r instanceof BufferedReader )
{
this.r = (BufferedReader) r;
}
else
{
this.r = new BufferedReader(r);
}
if ( this.r == null )
{
throw new IllegalArgumentException("invalid Reader");
} this.separator = separator;
this.quote = quote;
this.allowMultiLineFields = allowMultiLineFields;
this.trim = trim;
} /**
* convenience Constructor, default to comma separator, " for quote,
* no multiline fields, with trimming.
*
* @param r input Reader source of CSV Fields to read.
*/
public CSVReader (Reader r)
{
this(r, ',', '\"', false, true );
}
/**
* Reader source of the CSV fields to be read.
*/
private BufferedReader r; /**
* field separator character, usually ',' in North America,
* ';' in Europe and sometimes '\t' for tab.
*/
private final char separator; /**
* quote character, usually '\"'
* '\'' for SOL used to enclose fields containing a separator character.
*/
private final char quote; /**
* true if reader should allow
* quoted fields to span
* more than one line. Microsoft Excel
* sometimes generates files like this.
*/
private final boolean allowMultiLineFields; /**
* true if reader should trim lead/trail whitespace
* from fields returned.
*/
private final boolean trim;
/**
* category of end of line char.
*/
private static final int EOL = 0; /**
* category of ordinary character
*/
private static final int ORDINARY = 1; /**
* categotory of the quote "
*/
private static final int QUOTE = 2; /**
* category of the separator, e.g. comma, semicolon
* or tab.
*/
private static final int SEPARATOR = 3; /**
* category of characters treated as white space.
*/
private static final int WHITESPACE = 4; /**
* e.g. \n \r\n or \r, whatever system uses to separate lines in a text file.
*/
static String lineSeparator = System.getProperty ( "line.separator" );
static {
if ( lineSeparator == null )
{
lineSeparator = "\015012"; /* crlf in octal */
}
}
/**
* categorise a character for the finite state machine.
*
* @param c the character to categorise
* @return integer representing the character's category.
*/
private int categorise ( char c )
{
switch ( c )
{
case ' ':
case '\r':
case 0xff:
return WHITESPACE; case '\n':
return EOL; /* artificially applied to end of line */ default:
if ( c == quote )
{
return QUOTE;
}
else if ( c == separator /* dynamically determined so can't use as case label */ )
{
return SEPARATOR;
}
/* do our tests in crafted order, hoping for an early return */
else if ( '!' <= c && c <= '~' )
{
return ORDINARY;
}
else if ( 0x00 <= c && c <= 0x20 )
{
return WHITESPACE;
}
else if ( Character.isWhitespace(c) )
{
return WHITESPACE;
}
else
{
return ORDINARY;
}
}
} /**
* parser: We are in blanks before the field.
*/
private static final int SEEKING_START = 0; /**
* parser: We are in the middle of an ordinary field.
*/
private static final int IN_PLAIN = 1; /**
* parser: e are in middle of field surrounded in quotes.
*/
private static final int IN_QUOTED = 2; /**
* parser: We have just hit a quote, might be doubled
* or might be last one.
*/
private static final int AFTER_END_QUOTE = 3; /**
* parser: We are in blanks after the field looking for the separator
*/
private static final int SKIPPING_TAIL = 4; /**
* state of the parser's finite state automaton.
*/ /**
* The line we are parsing.
* null means none read yet.
* Line contains unprocessed chars. Processed ones are removed.
*/
private String line = null; /**
* How many lines we have read so far.
* Used in error messages.
*/
private int lineCount = 0;
/**
* false means next EOL s an empty field
* true means next EOL s the end of all fields.
*/
private boolean allFieldsDone = true;
/**
* Get all fields in the line
*
* @return Array of strings, one for each field.
* Possibly empty, but never null.
* @exception EOFException
* @exception IOException
*/
public String[] getAllFieldsInLine() throws EOFException, IOException
{
ArrayList al = new ArrayList( 30 );
do
{
String field = get();
if ( field == null )
{
break;
}
al.add (field);
}
while ( true );
return(String[])(al.toArray( new String[ al.size() ] ));
}
* Read one field from the CSV file
*
* @return String value, even if the field is numeric. Surrounded
* and embedded double quotes are stripped.
* possibly "". null means end of line.
*
* @exception EOFException
* at end of file after all the fields have
* been read.
*
* @exception IOException
* Some problem reading the file, possibly malformed data.
*/
public String get() throws EOFException, IOException
{ StringBuffer field = new StringBuffer( allowMultiLineFields ? 512 : 64 );
/* we implement the parser as a finite state automaton with five states. */
int state = SEEKING_START; /* start seeking, even if partway through a line */
/* don't need to maintain state between fields. */ lineLoop:
while ( true )
{ getLineIfNeeded(); charLoop:
/* loop for each char in the line to find a field */
/* guaranteed to leave early by hitting EOL */
for ( int i=0; i<line.length(); i++ )
{
char c = line.charAt(i);
int category = categorise(c);
if ( false )
{
// for debugging
System.out.println("char:"+c + " state:" + state + " field:" +field.length());
}
switch ( state )
{
case SEEKING_START:
{ /* in blanks before field */
switch ( category )
{
case WHITESPACE:
/* ignore */
break; case QUOTE:
state = IN_QUOTED;
break; case SEPARATOR:
/* end of empty field */
line = line.substring(i+1);
return ""; case EOL:
/* end of line */
if ( allFieldsDone )
{
/* null to end of line */
line = null;
return null;
}
else
{
/* empty field, usually after a comma */
allFieldsDone = true;
line = line.substring(i);
return "";
} case ORDINARY:
field.append(c);
state = IN_PLAIN;
break;
}
break;
}
case IN_PLAIN:
{ /* in middle of ordinary field */
switch ( category )
{
case QUOTE:
throw new IOException("Malformed CSV stream. Missing quote at start of field on line "+lineCount); case SEPARATOR:
/* done */
line = line.substring(i+1);
return maybeTrim( field.toString() ); case EOL:
line = line.substring(i); /* push EOL back */
allFieldsDone = true;
return maybeTrim( field.toString() ); case WHITESPACE:
field.append(' ');
break; case ORDINARY:
field.append(c);
break;
}
break;
} case IN_QUOTED:
{ /* in middle of field surrounded in quotes */
switch ( category )
{ case QUOTE:
state = AFTER_END_QUOTE;
break; case EOL:
if ( allowMultiLineFields )
{
field.append( lineSeparator );
// we are done with that line, but not with the field.
// We don't want to return a null
// to the end of the line.
line = null;
// will read next line and seek the end of the quoted field.
// with state = IN_QUOTED.
break charLoop;
}
else
{
// no multiline fields allowed
allFieldsDone = true;
throw new IOException ("Malformed CSV stream. Missing quote (\") after field on line "+lineCount);
}
case WHITESPACE:
field.append(' ');
break; case SEPARATOR:
case ORDINARY:
field.append(c);
break;
}
break;
}
{ /* In situation like this "xxx" which may
turn out to be xxx""xxx" or "xxx",
We find out here. */
switch ( category )
{ case QUOTE:
/* was a double quote, e.g. a literal " */
field.append(c);
state = IN_QUOTED;
break; case SEPARATOR :
/* we are done with field.*/
line = line.substring(i+1);
return maybeTrim( field.toString() ); case EOL:
line = line.substring(i); /* push back eol */
allFieldsDone = true;
return maybeTrim( field.toString() ); case WHITESPACE:
/* ignore trailing spaces up to separator */
state = SKIPPING_TAIL;
break; case ORDINARY:
throw new IOException("Malformed CSV stream, missing separator after fieldon line "+lineCount);
}
break;
} case SKIPPING_TAIL:
{
/* in spaces after field seeking separator */ switch ( category )
{ case SEPARATOR :
/* we are done.*/
line = line.substring(i+1);
return maybeTrim( field.toString() ); case EOL:
line = line.substring(i); /* push back eol */
allFieldsDone = true;
return maybeTrim( field.toString() ); case WHITESPACE:
/* ignore trailing spaces up to separator */
break; case QUOTE:
case ORDINARY:
throw new IOException("Malformed CSV stream, missing separator after field on line "+lineCount);
}
break;
} } // end switch(state) } // end charLoop
} // end lineLoop
} // end get /**
* Trim the string, but only if we are in
* trimming mode.
*
* @param s String to be trimmed.
* @return String or trimmed string.
*/
private String maybeTrim (String s )
{
if ( trim )
{
return s.trim();
}
else
{
return s;
}
}