Использование CSV в ActionScript


таблица CSV

CSV это формат хранения данных, который используется уже довольно давно. Он представляет собой самый простой способ хранить информацию в виде таблицы и может использоваться в множестве различных приложений.

Эта статья расскажет вам о том, как можно работать с CSV во Flash. Мы вместе напришем класс ActionScript 2.0, который будет обладать всей необходимой функциональностью для использования данных в формате CSV. А затем посмотрим как можно использовать компонент Data Grid для представления данных.

Почему именно CSV-формат?

CSV — очень простой формат. Данные хранятся в одном большом string-е, который содержит строки разделенные переносом строки, и столбцы, разделенные запятой(обычно). Благодаря такой незамысловатости он идеален для простых записей, в то время как XML-форматированные записи более сложны.

Другая важная причина, по которой этот формат так популярен, — то, что многие десктопные приложения способны работать с ним. Любая программа, оперирующая электронными таблицами (к примеру, Microsoft Excel), может просматривать, изменять, создавать CSV-файлы. В отличие от XML-форматированных записей, пользователь может просто открыть CSV-файл и легко просмотреть информацию.

Также как XML, CSV — это данные форматированные внутри файла. Он не связан ни с каким специфическим ПО или платформой, и ему не нужно сервера, чтобы быть доставленным клиенту. Это делает CSV и XML очень универсальными способами хранения данных. Вы можете создать flash-приложение основанное на web, а потом без лишних проблем использовать тот же код для постройки CD-ROM-приложения.

CSV не всегда правильное решение для вашего проекта. Благодаря своей гибкости, XMl обычно лучший способ передачи данных клиенту. Следует избегать использования CSV, когда ваши данные не представлены в виде набора строк и столбцов или содержат множественные уровни вложенности. Например, если в одной из ячеек содержится массив или список. XML в этом смысле лучше для разделения разных типов данных и обработки нескольких уровней вложенности. Используйте CSV только для базовых типов данных (String, Number и булевых), которые могут храниться в ячейках таблицы.

Описание CSV

Первое, что вы должны знать об этом формате — то, что данные состоят из строк и стобцов. Строки разделяются переносом строки (\n), возвратом каретки (\r) или их комбинацией. Столбцы разделяются обычно запятой (отсюда название - "Comma Separated Values"). Часто первая строка файла используется для задания заголовков столбцов; мы поговорим больше об этом когда будем парсить файл в нашем классе.

Довольно часто в CSV-файлах используется qualifier, в основном двойная кавычка ("). Этот символ используется для точного ограничения значения ячейки. Ниже представлены примеры с ним и без него:

CSV-данные без qualifier-а:

Field 1,Field 2,Field 3,Field 4
Field 5,Field 6,Field 7,Field 8

CSV-данные с qualifier-ом:

"Field 1","Field 2","Field 3","Field 4"
"Field 5","Field 6","Field 7","Field 8"

Создание класса CSV

Перед тем, как мы начнем писать наш CSV-класс, нужно уточнить что он должен делать:

  1. Класс должен загружать внешний CSV-файл.
  2. Класс должен парсить данные и создавать Flash объект. Форматом, в котором мы вернем данные, будет массив объектов (или ассоциативных массивов), с ключом - заголовком колонки.
  3. Разбор данных должен выбрать заголовки столбцов и первой строки CSV; кроме того, мы должны дать возможность пользователю переопределить названия колонок.
  4. Парсер также должен поддерживать qualifier-ы. Мы позволим пользователю определять их перед парсингом.

Начнем создание класса с его определения. Конструктор оставим пустым, так как он ничего не будет делать.

class CSV {
   function CSV() {}
}

Теперь опишем параметры класса:

  • • csvData — private массив, в котором будем хранить распарсенные данные.
  • • onLoad — public метод, который можно переопределить.
  • • columns — public массив, который пользователь вправе задать сам перед парсингом файла.
  • • qualifier — public строка, задаваемая пользователем перед парсингом данных. По умолчанию пусть будет пустая строка.
private var csvData:Array;
public var onLoad:Function;
public var columns:Array;
public var qualifier:String = '';

Первая задача, которая будет выполнятся классом — загрузка данных из файла. Мы реализуем это, создав метод load, который будет получать в качестве своего единственного параметра путь к CSV-файлу. Метод будет использовать класс LoadVars, чтобы загрузить файл, но мы используем неопределенный метод onData в классе LoadVars. Этот метод работает в точности как XML.onData. Он позволит нам получить raw-данные без разбора их классом LoadVars.

public function load(csvPath:String):Void {
   var csvLoad:LoadVars = new LoadVars();
   csvLoad._parent = this;
   csvLoad.onData = function(rawData:String) {
      this._parent.onData(rawData);
   }
   csvLoad.load(csvPath);
}

Заметьте, что в методе LoadVars.onData мы вызываем метод onData нашего класса. onData будет парсить данные после загрузки файла. Как только разбор завершится, данные передадутся назад пользователю через onLoad-метод. Мы не будем в явном виде определять метод onLoad. Юзеры также смогут переопределить метод onData, если они не пожелают парсить данные сразу же.

public function onData(rawData:String):Void {
   csvData = parseCSV(rawData);
   onLoad();
}

Теперь мы добавим функцию разбора. Сделаем этот метод public для того, чтобы можно было его использовать не только для загружаемых файлов. Парсер -- самая сложная часть этого класса, так как здесь могут возникнуть разные ошибки.

Наш парсер будет получать в качестве единственного параметра сырой csv-текст, а возвращать форматированный массив объектов. Первые две вещи, которые он должен уметь -- определять разделители строк и столбцов. Мы уже знаем, что строки разделяет \r, \n или \r\n. С помощью быстрого поиска мы определим какой из них точно. Разделителем колонок будем считать запятую; как бы то ни было мы можем сделать синтаксический разбор более точным с помощью добавления qualifier-а до и после разделителя.

Сначала разделим исходный csv-текст на массив строк. Это позволит нам пройтись по нему и разобрать каждую строку в отдельности.

Если названия колонок не были определены перед парсингом, мы будем полагать, что первая строка файла содержит названия колонок. Тогда мы будем заполнять массив в соответствии с ними.

Проходя по массиву строк, мы разбиваем каждую на массив ячеек. Если их число не совпадает с числом колонок файла, мы пропускаем эту строку. Перебирая ячейки мы заносим данные в объект, используя в качестве ключа заголовок столбца файла. После этого добавляем этот объект в массив, который будет возвращаться пользователю:

public function parseCSV(rawData:String):Array {
   var ii:Number, columnArray:Array, rowObject:Object;
   var returnArray:Array = new Array();
   var rowDelimiter:String = (rawData.indexOf('\r\n') > -1) ? '\r\n' :
      (rawData.indexOf('\r') > -1) ? '\r' : '\n';
   var columnDelimiter:String = qualifier + ',' + qualifier;
   var rowsArray:Array = rawData.split(rowDelimiter);
   if(!columns.length) {
      columns = removeQualifier(rowsArray.shift().toString(),
      qualifier).split(columnDelimiter);
   }
   for(var i:Number = 0; i < rowsArray.length; i++) {
      columnArray = removeQualifier(rowsArray[i].toString(),
      qualifier).split(columnDelim);
      if(columnArray.length == columns.length) {
         rowObject = new Object();
         for(ii = (columnArray.length - 1); ii >= 0; ii--) {
            rowObject[columns[ii]] = columnArray[ii];
         }
         returnArray.push(rowObject);
      }
   }
   return returnArray;
}

Здесь необходимо создать private метод removeQualifier, который будет использоваться парсером. Он будет убирать qualifier с начала и с конца ячейки данных:

private function removeQualifier(originalString:String, qualifier:String):String {
   var modifiedString = originalString;
   if(modifiedString.charAt(0) == qualifier) {
      modifiedString = modifiedString.substring(1);
   }
   if(modifiedString.charAt(modifiedString.length - 1) == qualifier) {
      modifiedString = modifiedString.substring(0, (modifiedString.length - 1));
   }
   return modifiedString;
}

Чтобы вернуть внутрениий параметр csvData, создадим getter метод data. Его действие будет очень простым -- он будет возвращать распарсенные данные юзеру. Мы делаем это для защиты csvData от записи снаружи класса.

public function get data():Array {
   return csvData;
}

Использование CSV-класса с компонентом Data Grid

В этом примере посмотрим как можно использовать компонент Data Grid для отображения наших CSV-данных. Параметр dataProvider данного компонента принимает массив объектов, как раз как у нас. Первое — нужно поместить инстанцию компонента на stage и указать ей instance name (пусть dataGrid_mc). Затем создайте слой "Actions" и поместите следующий код в его первый фрейм. Убедитесь что файл класса лежит в той же папке, что и FLA-файл.

Первое — создаем экземпляр класса:

var csvLoad:CSV = new CSV();

Затем, задаем столбцы и qualifier:

csvLoad.columns = new Array('Column 1', 'Column 2', 'Column 3');
csvLoad.qualifier = '"';

И последнее — определяем метод onLoad, в котором отдадим данные инстанции компонента Data Grid, а потом начинаем загрузку csv-файла:

csvLoad.onLoad = function() {
   dataGrid_mc.dataProvider = this.data;
}
csvLoad.load('sampleData.csv');

Эпилог

Надеюсь эта статья даст вам идеи каким образом можно использовать CSV-данные в вашем Flash-приложении. И, что более важно, я надеюсь она покажет вам конкретный пример построения классов в ActionScript 2.0, удобных для использования и поддержки. Класс CSV может и не быть решением для вашего проекта, однако приведенные принципы объектно-ориентированного программирования следует стараться использовать практически в каждом вашем Flash-приложении.

В прикрепленном архиве находится пример полного кода, разобранного в статье.

Оригинал CSV in Flash MX 2004
Перевод 3hrek

Прикрепленный файлРазмер
csv-actionscript.rar89.64 кб

Комментарии

Не отображаются русские символы (((
Корректно работает только с латиницей

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Разрешаю теги: <a> <em> <strong> <pre> <ul> <ol> <li>
  • Строки и параграфы переносятся автоматически.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.

Подробнее о форматировании

Image CAPTCHA
Регистр символов учитывается.