导入CSV——csv_to_grid
脚本说明
该脚本用于读取csv文件,并将其中的数据导入为ds_grid进行调用
参数说明
参数序号 | 参数名 | 数据类型 | 参数说明 |
---|---|---|---|
arg0 | file | String | UTF-8格式的csv文件名 |
arg1 | froce_sgrings | Bool | 是否强制把所有单元格的内容转成字符串,默认为false |
arg2 | cell_delimiter | String | 划分单元格的分隔符,默认为逗号 |
arg3 | string_delimiter | string | 定义字符串的符号,默认为双引号 |
arg4 | mac_newline | Bool | 是否兼容Mac平台的换行符(0A)。默认为Windows的换行符(0D,0A) |
逆向方法参数说明
参数序号 | 参数名 | 数据类型 | 参数说明 |
---|---|---|---|
arg0 | grid | ds_grid | 要转换成csv格式的grid表的索引ID |
arg1 | field_delimiter | String | 定义划分单元格的分隔符,默认为逗号 |
arg2 | string_delimiter | string | 定义在csv中区分字符串的符号,默认为双引号 |
arg3 | newline | String | 定义换行符(0A)。默认为Windows的换行符(0D,0A) |
GMS2版代码
/// @desc csv_to_grid
/// @param file
/// @param [force_strings]
/// @param [cell_delimiter]
/// @param [string_delimiter]
/// @param [mac_newline]
//
// CAUTION: Please ensure your files are in UTF-8 encoding.
//
// You may pass <undefined> to use the default value for optional arguments.
// arg0 string Filename for the source UTF-8 CSV file
// arg1 bool Whether to force all cells to be a string. Defaults to false
// arg2 string The delimiter used to separate cells. Defaults to a comma
// arg3 string The delimiter used to define strings in the CSV file. Defaults to a double-quote
// arg4 bool Newline compatibility mode for Mac (0A). Defaults to Windows standard newline (0D,0A)
//
// (c) Juju Adams 26th May 2017
// @jujuadams
//Handle arguments
if ( argument_count < 1 ) or ( argument_count > 5 ) {
show_error( "Incorrect number of arguments (" + string( argument_count ) + ")", false );
return undefined;
}
var _filename = argument[0];
var _force_strings = false;
var _cell_delimiter = chr(44); //comma
var _string_delimiter = chr(34); //double-quote
var _newline_alt = false;
if ( argument_count >= 2 ) and ( !is_undefined( argument[1] ) ) _force_strings = argument[1];
if ( argument_count >= 3 ) and ( !is_undefined( argument[2] ) ) _cell_delimiter = argument[2];
if ( argument_count >= 4 ) and ( !is_undefined( argument[3] ) ) _string_delimiter = argument[3];
if ( argument_count >= 5 ) and ( !is_undefined( argument[4] ) ) _newline_alt = argument[4];
//Check for silliness...
if ( string_length( _cell_delimiter ) != 1 ) or ( string_length( _string_delimiter ) != 1 ) {
show_error( "Delimiters must be one character", false );
return undefined;
}
//More variables...
var _cell_delimiter_ord = ord( _cell_delimiter );
var _string_delimiter_ord = ord( _string_delimiter );
var _sheet_width = 0;
var _sheet_height = 1;
var _max_width = 0;
var _prev_val = 0;
var _val = 0;
var _str = "";
var _in_string = false;
var _is_decimal = !_force_strings;
var _grid = ds_grid_create( 1, 1 ); _grid[# 0, 0 ] = "";
//Load CSV file as a buffer
var _buffer = buffer_load( _filename );
var _size = buffer_get_size( _buffer );
buffer_seek( _buffer, buffer_seek_start, 0 );
//Handle byte order marks from some UTF-8 encoders (EF BB BF at the start of the file)
var _bom_a = buffer_read( _buffer, buffer_u8 );
var _bom_b = buffer_read( _buffer, buffer_u8 );
var _bom_c = buffer_read( _buffer, buffer_u8 );
if !( ( _bom_a == 239 ) and ( _bom_b == 187 ) and ( _bom_c == 191 ) ) {
show_debug_message( "CAUTION: csv_to_grid: " + _filename + ": CSV file might not be UTF-8 encoded (no BOM)" );
buffer_seek( _buffer, buffer_seek_start, 0 );
} else {
_size -= 3;
}
//Iterate over the buffer
for( var _i = 0; _i < _size; _i++ ) {
_prev_val = _val;
var _val = buffer_read( _buffer, buffer_u8 );
//Handle UTF-8 encoding
if ( ( _val & 224 ) == 192 ) { //two-byte
_val = ( _val & 31 ) << 6;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 );
_i++;
} else if ( ( _val & 240 ) == 224 ) { //three-byte
_val = ( _val & 15 ) << 12;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 6;
_val += buffer_read( _buffer, buffer_u8 ) & 63;
_i += 2;
} else if ( ( _val & 248 ) == 240 ) { //four-byte
_val = ( _val & 7 ) << 18;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 12;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 6;
_val += buffer_read( _buffer, buffer_u8 ) & 63;
_i += 3;
}
//If we've found a string delimiter
if ( _val == _string_delimiter_ord ) {
//This definitely isn't a decimal number!
_is_decimal = false;
//If we're in a string...
if ( _in_string ) {
//If the next character is a string delimiter itself, skip this character
if ( buffer_peek( _buffer, buffer_tell( _buffer ), buffer_u8 ) == _string_delimiter_ord ) continue;
//If the previous character is a string delimiter itself, add the string delimiter to the working string
if ( _prev_val == _string_delimiter_ord ) {
_str += _string_delimiter;
continue;
}
}
//Toggle "we're in a string" behaviour
_in_string = !_in_string;
continue;
}
if ( _newline_alt ) {
var _newline = ( _val == 10 );
} else {
var _newline = ( _prev_val == 13 ) and ( _val == 10 );
//If we've found a newline and we're in a string, skip over the chr(10) character
if ( _in_string ) and ( _newline ) continue;
}
//If we've found a new cell
if ( ( _val == _cell_delimiter_ord ) or ( _newline ) ) and ( !_in_string ) {
_sheet_width++;
//If this cell is now longer than the maximum width of the grid, expand the grid
if ( _sheet_width > _max_width ) {
_max_width = _sheet_width;
ds_grid_resize( _grid, _max_width, _sheet_height );
//Clear cells vertically above to overwrite the default 0-value
if ( _sheet_height >= 2 ) ds_grid_set_region( _grid, _max_width-1, 0, _max_width-1, _sheet_height-2, "" );
}
//Write the working string to a grid cell
if ( _is_decimal ) _str = real( _str );
_grid[# _sheet_width-1, _sheet_height-1 ] = _str;
_str = "";
_in_string = false;
_is_decimal = !_force_strings;
//A newline outside of a string triggers a new line... unsurprisingly
if ( _newline ) {
//Clear cells horizontally to overwrite the default 0-value
if ( _sheet_width < _max_width ) ds_grid_set_region( _grid, _sheet_width, _sheet_height-1, _max_width-1, _sheet_height-1, "" );
_sheet_width = 0;
_sheet_height++;
ds_grid_resize( _grid, _max_width, _sheet_height );
}
continue;
}
//Check if we've read a "\n" dual-character
if ( _prev_val == 92 ) and ( _val == 110 ) {
_str = string_delete( _str, string_length( _str ), 1 ) + chr(13);
continue;
}
//No newlines should appear outside of a string delimited cell
if ( ( _val == 10 ) or ( _val == 13 ) ) and ( !_in_string ) continue;
//Check if this character is outside valid decimal character range
if ( _val != 45 ) and ( _val != 46 ) and ( ( _val < 48 ) or ( _val > 57 ) ) _is_decimal = false;
//Finally add this character to the working string!
_str += chr( _val );
}
//Catch hanging work string on end-of-file
if ( _str != "" ) {
_sheet_width++;
if ( _sheet_width > _max_width ) {
_max_width = _sheet_width;
ds_grid_resize( _grid, _max_width, _sheet_height );
if ( _sheet_height >= 2 ) ds_grid_set_region( _grid, _max_width-1, 0, _max_width-1, _sheet_height-2, "" );
}
if ( _is_decimal ) _str = real( _str );
_grid[# _sheet_width-1, _sheet_height-1 ] = _str;
}
//If the last character was a newline then we'll have an erroneous extra row at the bottom
if ( _newline ) ds_grid_resize( _grid, _max_width, _sheet_height-1 );
buffer_delete( _buffer );
return _grid;
GMS1版代码
///csv_to_grid( file, force strings, cell delimiter, string delimiter, mac newline )
//
// CAUTION: Please ensure your files are in UTF-8 encoding.
//
// You may pass <undefined> to use the default value for optional arguments.
// arg0 string Filename for the source UTF-8 CSV file
// arg1 bool Whether to force all cells to be a string. Defaults to false
// arg2 string The delimiter used to separate cells. Defaults to a comma
// arg3 string The delimiter used to define strings in the CSV file. Defaults to a double-quote
// arg4 bool Newline compatibility mode for Mac (0A). Defaults to Windows standard newline (0D,0A)
//
// (c) Juju Adams 26th May 2017
// @jujuadams
//Handle arguments
if ( argument_count < 1 ) or ( argument_count > 5 ) {
show_error( "Incorrect number of arguments (" + string( argument_count ) + ")", false );
return undefined;
}
var _filename = argument[0];
var _force_strings = false;
var _cell_delimiter = chr(44); //comma
var _string_delimiter = chr(34); //double-quote
var _newline_alt = false;
if ( argument_count >= 2 ) and ( !is_undefined( argument[1] ) ) _force_strings = argument[1];
if ( argument_count >= 3 ) and ( !is_undefined( argument[2] ) ) _cell_delimiter = argument[2];
if ( argument_count >= 4 ) and ( !is_undefined( argument[3] ) ) _string_delimiter = argument[3];
if ( argument_count >= 5 ) and ( !is_undefined( argument[4] ) ) _newline_alt = argument[4];
//Check for silliness...
if ( string_length( _cell_delimiter ) != 1 ) or ( string_length( _string_delimiter ) != 1 ) {
show_error( "Delimiters must be one character", false );
return undefined;
}
//More variables...
var _cell_delimiter_ord = ord( _cell_delimiter );
var _string_delimiter_ord = ord( _string_delimiter );
var _sheet_width = 0;
var _sheet_height = 1;
var _max_width = 0;
var _prev_val = 0;
var _val = 0;
var _str = "";
var _in_string = false;
var _is_decimal = !_force_strings;
var _grid = ds_grid_create( 1, 1 ); _grid[# 0, 0 ] = "";
//Load CSV file as a buffer
var _buffer = buffer_load( _filename );
var _size = buffer_get_size( _buffer );
buffer_seek( _buffer, buffer_seek_start, 0 );
//Handle byte order marks from some UTF-8 encoders (EF BB BF at the start of the file)
var _bom_a = buffer_read( _buffer, buffer_u8 );
var _bom_b = buffer_read( _buffer, buffer_u8 );
var _bom_c = buffer_read( _buffer, buffer_u8 );
if !( ( _bom_a == 239 ) and ( _bom_b == 187 ) and ( _bom_c == 191 ) ) {
show_debug_message( "CAUTION: csv_to_grid: " + _filename + ": CSV file might not be UTF-8 encoded (no BOM)" );
buffer_seek( _buffer, buffer_seek_start, 0 );
} else {
_size -= 3;
}
//Iterate over the buffer
for( var _i = 0; _i < _size; _i++ ) {
_prev_val = _val;
var _val = buffer_read( _buffer, buffer_u8 );
//Handle UTF-8 encoding
if ( ( _val & 224 ) == 192 ) { //two-byte
_val = ( _val & 31 ) << 6;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 );
_i++;
} else if ( ( _val & 240 ) == 224 ) { //three-byte
_val = ( _val & 15 ) << 12;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 6;
_val += buffer_read( _buffer, buffer_u8 ) & 63;
_i += 2;
} else if ( ( _val & 248 ) == 240 ) { //four-byte
_val = ( _val & 7 ) << 18;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 12;
_val += ( buffer_read( _buffer, buffer_u8 ) & 63 ) << 6;
_val += buffer_read( _buffer, buffer_u8 ) & 63;
_i += 3;
}
//If we've found a string delimiter
if ( _val == _string_delimiter_ord ) {
//This definitely isn't a decimal number!
_is_decimal = false;
//If we're in a string...
if ( _in_string ) {
//If the next character is a string delimiter itself, skip this character
if ( buffer_peek( _buffer, buffer_tell( _buffer ), buffer_u8 ) == _string_delimiter_ord ) continue;
//If the previous character is a string delimiter itself, add the string delimiter to the working string
if ( _prev_val == _string_delimiter_ord ) {
_str += _string_delimiter;
continue;
}
}
//Toggle "we're in a string" behaviour
_in_string = !_in_string;
continue;
}
if ( _newline_alt ) {
var _newline = ( _val == 10 );
} else {
var _newline = ( _prev_val == 13 ) and ( _val == 10 );
//If we've found a newline and we're in a string, skip over the chr(10) character
if ( _in_string ) and ( _newline ) continue;
}
//If we've found a new cell
if ( ( _val == _cell_delimiter_ord ) or ( _newline ) ) and ( !_in_string ) {
_sheet_width++;
//If this cell is now longer than the maximum width of the grid, expand the grid
if ( _sheet_width > _max_width ) {
_max_width = _sheet_width;
ds_grid_resize( _grid, _max_width, _sheet_height );
//Clear cells vertically above to overwrite the default 0-value
if ( _sheet_height >= 2 ) ds_grid_set_region( _grid, _max_width-1, 0, _max_width-1, _sheet_height-2, "" );
}
//Write the working string to a grid cell
if ( _is_decimal ) _str = real( _str );
_grid[# _sheet_width-1, _sheet_height-1 ] = _str;
_str = "";
_in_string = false;
_is_decimal = !_force_strings;
//A newline outside of a string triggers a new line... unsurprisingly
if ( _newline ) {
//Clear cells horizontally to overwrite the default 0-value
if ( _sheet_width < _max_width ) ds_grid_set_region( _grid, _sheet_width, _sheet_height-1, _max_width-1, _sheet_height-1, "" );
_sheet_width = 0;
_sheet_height++;
ds_grid_resize( _grid, _max_width, _sheet_height );
}
continue;
}
//Check if we've read a "#" character
if ( _prev_val == 35 ) {
_str += chr(13);
continue;
}
//No newlines should appear outside of a string delimited cell
if ( ( _val == 10 ) or ( _val == 13 ) ) and ( !_in_string ) continue;
//Check if this character is outside valid decimal character range
if ( _val != 45 ) and ( _val != 46 ) and ( ( _val < 48 ) or ( _val > 57 ) ) _is_decimal = false;
//Finally add this character to the working string!
_str += chr( _val );
}
//Catch hanging work string on end-of-file
if ( _str != "" ) {
_sheet_width++;
if ( _sheet_width > _max_width ) {
_max_width = _sheet_width;
ds_grid_resize( _grid, _max_width, _sheet_height );
if ( _sheet_height >= 2 ) ds_grid_set_region( _grid, _max_width-1, 0, _max_width-1, _sheet_height-2, "" );
}
if ( _is_decimal ) _str = real( _str );
_grid[# _sheet_width-1, _sheet_height-1 ] = _str;
}
//If the last character was a newline then we'll have an erroneous extra row at the bottom
if ( _newline ) ds_grid_resize( _grid, _max_width, _sheet_height-1 );
buffer_delete( _buffer );
return _grid;
逆向代码
///grid_to_csv_string( grid, [field delimiter], [string delimiter], [newline] )
//
// arg0 ds_grid The grid holding the data to be formatted/encoded to CSV
// arg1 string The field delimiter used to separate cells (cannot be a decimal point). Defaults to a comma
// arg2 string The string delimiter used to define strings in the CSV file. Defaults to a double-quote
// arg3 string The newline character(s) used to defined a new row. Defaults to the Windows standard (0D,0A)
//
// returns: A string containing a formatted CSV file, including line breaks
//
// (c) Juju Adams 5th March 2017 - All Rights Reserved
// @jujuadams
var _grid = undefined;
var _field_delimiter = chr(44); //comma
var _string_delimiter = chr(34); //double-quote
var _newline = chr(13) + chr(10); //default Windows (Notepad) newline
if ( argument_count <= 0 ) and ( argument_count > 4 ) {
show_error( "Incorrect number of arguments (" + string( argument_count ) + ")", false );
return "";
}
if ( argument_count >= 1 ) var _grid = argument[0];
if ( argument_count >= 2 ) var _field_delimiter = argument[1];
if ( argument_count >= 3 ) var _string_delimiter = argument[2];
if ( argument_count >= 4 ) var _newline = argument[3];
if ( _field_delimiter == chr(46) ) { //decimal point
show_error( "Field delimiter cannot be a decimal point!", false );
return "";
}
var _str = "";
var _width = ds_grid_width( _grid );
var _height = ds_grid_height( _grid );
for( var _y = 0; _y < _height; _y++ ) {
for( var _x = 0; _x < _width; _x++ ) {
var _value = _grid[# _x, _y ];
if ( is_real( _value ) ) {
_str += string( _value );
} else if ( is_string( _value ) ) {
if ( _value != "" ) { //Catch empty strings
_str += _string_delimiter + string_replace_all( _value, _string_delimiter, _string_delimiter+_string_delimiter ) + _string_delimiter;
}
} else {
show_debug_message( "ds_grid_to_csv: CAUTION - grid " + string( _grid ) + " value at " + string( _x ) + "," + string( _y ) + " is not a valid datatype!" );
}
if ( _x < _width-1 ) _str += _field_delimiter;
}
_str += _newline;
}
return _str;
旧版GMS1代码
///csv_to_grid( file, [cell delimiter], [text delimiter] )
//
// Loads a .csv file into a ds_grid that is automatically sized to the data.
// Useful for translations, dialogue trees, mods etc.
//
// January 2016
// @jujuadams
//Collect the filename. You don't strictly have to do this but it's good practice for larger scripts in case you need to change things around
switch( argument_count ) {
case 1:
var file = argument[0];
var cellDelimiter = "";
var textDelimiter = "";
break;
case 2:
var file = argument[0];
var cellDelimiter = argument[1];
var textDelimiter = "";
break;
case 3:
var file = argument[0];
var cellDelimiter = argument[1];
var textDelimiter = argument[2];
break;
default:
cout( "scr_juju_csv_load_to_grid: Error! Unsupported number of arguments" );
return noone;
break;
}
if ( cellDelimiter == "" ) cellDelimiter = ",";
if ( textDelimiter == "" ) textDelimiter = chr(34);
var cellDelimiterOrd = ord( cellDelimiter );
var textDelimiterOrd = ord( textDelimiter );
//
var buffer = buffer_create( 1, buffer_grow, 1 );
buffer_load_ext( buffer, file, 0 );
buffer_seek( buffer, buffer_seek_start, 0 );
//Initialise width and height of the spreadsheet
var sheetWidth = 0;
var sheetHeight = 1;
var prevVal = 0;
var nextVal = 0;
var val = 0;
var str = "";
var inText = false;
var grid = noone;
var size = buffer_get_size( buffer );
for( var i = 0; i < size; i++ ) {
prevVal = val;
var val = buffer_read( buffer, buffer_u8 );
if ( val == 13 ) continue;
if ( val == textDelimiterOrd ) {
var nextVal = buffer_peek( buffer, buffer_tell( buffer ), buffer_u8 );
if ( inText ) {
if ( nextVal == textDelimiterOrd ) continue;
if ( prevVal == textDelimiterOrd ) {
str += textDelimiter;
continue;
}
}
inText = !inText;
continue;
}
if ( inText ) and ( ( prevVal == 13 ) and ( val == 10 ) ) {
str += "#";
continue;
}
if ( ( val == cellDelimiterOrd ) or ( ( prevVal == 13 ) and ( val == 10 ) ) ) and ( !inText ) {
sheetWidth++;
if ( grid == noone ) {
grid = ds_grid_create( max( 1, sheetWidth ), max( 1, sheetHeight ) );
ds_grid_clear( grid, "" );
} else ds_grid_resize( grid, max( sheetWidth, ds_grid_width( grid ) ), sheetHeight );
ds_grid_set( grid, sheetWidth - 1, sheetHeight - 1, str );
str = "";
inText = false;
if ( val == 10 ) {
sheetWidth = 0;
sheetHeight++;
}
continue;
}
str += chr( val );
}
buffer_delete( buffer );
sheetWidth = ds_grid_width( grid );
sheetHeight = ds_grid_height( grid );
for( var yy = 0; yy < sheetHeight; yy++ ) {
for( var xx = 0; xx < sheetWidth; xx++ ) {
var val = ds_grid_get( grid, xx, yy );
if ( !is_string( val ) ) ds_grid_set( grid, xx, yy, "" );
}
}
//Return the grid, ready for use elsewhere
return grid;
本脚本转自GMLSCRIPT.COM,原作者Juju
原帖地址: csv_to_grid
Comments