- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个应用程序,我必须将数据从 CSV 文件上传到数据库表中。问题是,我没有 CSV 文件,但有要转换为 CSV 的纯文本文件。另一个问题是,由于该应用程序由具有不同系统的多个客户使用,因此我有不同布局的不同平面文本文件。
我想要实现的是创建一个从特殊文件加载“规则”的应用程序;这些规则将与纯文本文件一起处理,以生成 CSV 文件。从平面文件转换为 CSV 的应用程序是相同的,只是规则集不同。
我怎样才能实现这个目标?您推荐的最佳实践是什么?
最佳答案
这取决于规则的复杂程度。如果唯一不同的输入是列的名称和使用的分隔符,那么这很简单,但如果您还希望能够解析完全不同的格式(例如 XML 等),那么情况就不同了。
我自己会选择为“记录”读取器实现一个基类,该读取器从文件中读取记录并将其输出到数据集或 CSV。然后,您可以实现子类来实现读取不同的源格式。
如果您愿意,您可以为这些格式添加特定规则,这样您就可以创建一个继承自 BaseReader 的通用 XMLReader,但允许配置列名称。但我会从一堆针对您所获得的格式的硬编码阅读器开始,直到更清楚您可能会遇到这些格式的哪些方言。
编辑:根据要求,提供其外观的示例。
注意,这个例子远非理想!它读取自定义格式,将其传输到一个特定的表结构并将其另存为 CSV 文件。您可能想进一步拆分它,以便可以为不同的表结构重用代码。特别是字段定义,您可能希望能够在后代类或工厂类中进行设置。但为了简单起见,我采取了一种更严格的方法,并在一个基类中放置了太多的智能。
基类具有创建内存数据集所需的逻辑(我使用了 TClientDataSet)。它可以“迁移”文件。实际上,这意味着它读取、验证和导出文件。
读取是抽象的,必须在子类中实现。它应该将数据读取到内存数据集中。这允许您在客户端数据集中进行所有必要的验证。这允许您以与数据库/文件格式无关的方式强制执行字段类型和大小,并在需要时进行任何其他检查。
验证和写入是使用数据集中的数据完成的。从源文件解析为数据集的那一刻起,就不再需要了解源文件格式了。
声明:不要忘记使用DB、DBClient
。
type
TBaseMigrator = class
private
FData: TClientDataset;
protected
function CSVEscape(Str: string): string;
procedure ReadFile(AFileName: string); virtual; abstract;
procedure ValidateData;
procedure SaveData(AFileName: string);
public
constructor Create; virtual;
destructor Destroy; override;
procedure MigrateFile(ASourceFileName, ADestFileName: string); virtual;
end;
实现:
{ TBaseReader }
constructor TBaseMigrator.Create;
begin
inherited Create;
FData := TClientDataSet.Create(nil);
FData.FieldDefs.Add('ID', ftString, 20, True);
FData.FieldDefs.Add('Name', ftString, 60, True);
FData.FieldDefs.Add('Phone', ftString, 15, False);
// Etc
end;
function TBaseMigrator.CSVEscape(Str: string): string;
begin
// Escape the string to a CSV-safe format;
// Todo: Check if this is sufficient!
Result := '"' + StringReplace(Result, '"', '""', [rfReplaceAll]) + '"';
end;
destructor TBaseMigrator.Destroy;
begin
FData.Free;
inherited;
end;
procedure TBaseMigrator.MigrateFile(ASourceFileName, ADestFileName: string);
begin
// Read the file. Descendant classes need to override this method.
ReadFile(ASourceFileName);
// Validation. Implemented in base class.
ValidateData;
// Saving/exporting. For now implemented in base class.
SaveData(ADestFileName);
end;
procedure TBaseMigrator.SaveData(AFileName: string);
var
Output: TFileStream;
Writer: TStreamWriter;
FieldIndex: Integer;
begin
Output := TFileStream.Create(AFileName,fmCreate);
Writer := TStreamWriter.Create(Output);
try
// Write the CSV headers based on the fields in the dataset
for FieldIndex := 0 to FData.FieldCount - 1 do
begin
if FieldIndex > 0 then
Writer.Write(',');
// Column headers are escaped, but this may not be needed, since
// they likely don't contain quotes, commas or line breaks.
Writer.Write(CSVEscape(FData.Fields[FieldIndex].FieldName));
end;
Writer.WriteLine;
// Write each row
FData.First;
while not FData.Eof do
begin
for FieldIndex := 0 to FData.FieldCount - 1 do
begin
if FieldIndex > 0 then
Writer.Write(',');
// Escape each value
Writer.Write(CSVEscape(FData.Fields[FieldIndex].AsString));
end;
Writer.WriteLine;
FData.Next
end;
finally
Writer.Free;
Output.Free;
end;
end;
procedure TBaseMigrator.ValidateData;
begin
FData.First;
while not FData.Eof do
begin
// Validate the current row of FData
FData.Next
end;
end;
示例子类:TIniFileReader,它读取 inifile 部分,就好像它们是数据库记录一样。可以看到,您只需要实现读取文件的逻辑即可。
type
TIniFileReader = class(TBaseMigrator)
public
procedure ReadFile(AFileName: string); override;
end;
{ TIniFileReader }
procedure TIniFileReader.ReadFile(AFileName: string);
var
Source: TMemIniFile;
IDs: TStringList;
ID: string;
i: Integer;
begin
// Initialize an in-memory dataset.
FData.Close; // Be able to migrate multiple files with one instance.
FData.CreateDataSet;
// Parsing a weird custom format, where each section in an inifile is a
// row. Section name is the key, section contains the other fields.
Source := TMemIniFile.Create(AFileName);
IDs := TStringList.Create;
try
Source.ReadSections(IDs);
for i := 0 to IDs.Count - 1 do
begin
// The section name is the key/ID.
ID := IDs[i];
// Append a row.
FData.Append;
// Read the values.
FData['ID'] := ID;
FData['Name'] := Source.ReadString(ID, 'Name', '');
// Names don't need to match. The field 'telephone' in this propriety
// format maps to 'phone' in your CSV output.
// Later, you can make this customizable (configurable) if you need to,
// but it's unlikely that you encounter two different inifile-based
// formats, so it's a waste to implement that until you need it.
FData['Phone'] := Source.ReadString(ID, 'Telephone', '');
FData.Post;
end;
finally
IDs.Free;
Source.Free;
end;
end;
关于delphi - 解析平面文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12460210/
我有一个对象: [ { TEAMGROUP: "AB", TEAMNAME: "TEAM1", SPRINTS: [ { ID: 1,
颜色模型和颜色空间之间的差异 RGB565 与 RGB888 有何不同任何建议链接 YUV vs RGB vs YCbCr。? 最佳答案 RGB 是一种加法颜色模型,其中红色、绿色和蓝色强度以不同的组
我正在从单个顶点/索引缓冲区绘制一个具有多个网格的完整对象,并且它们具有不同的纹理。因此,我想到将纹理 ID 与顶点一起从顶点着色器传递到片段着色器中的片段。问题是禁用插值。我正在使用 GLSL ve
我有一个包含 40000 个 float 的数组,用于指定 map 上的高度级别。我想在 OpenGL ES 2.0 中创建一个网格/平面,为该网格中的每个顶点分配一个来自该数组的高度值,以便它们创建
我真的很喜欢 IQ 的页面以及有关 SDF 的信息: ( https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
我创建了 QPushButton在带有此样式表的 Qt Designer 中: QPushButton#pushButton { background-color: #ffffff; } QP
所以我正在寻找一些平面 map 的解决方法,因为它在 IE 上不起作用,我找到了这个:但我不太明白为什么它会起作用 var gadjets = [ {computers:['asus', 'hp'
child Actor 会不会太多?例如,如果我有一个有 10000 个 child Actor 的 Actor ,与每个有 1000 个 child Actor 的 10 个 Actor 相比,这会
我有一个由法线 (n) 和距离 (d)(距原点)定义的平面。我想把它改造成一个新的系统。 长路是这样的: 1) 将距离 (d) 与法线 (n) 相乘得到一个向量 (p) 2) 旋转 (R) 并平移 (
问题: 从球体中减去立方体会得到一个结果,其中 z 轴保留体积,但 y 轴和 x 轴产生平面圆盘,如图所示。我不确定为什么球体在那些方面正在失去体积。我正在使用 threeCSG 的典型减法。 代码:
我通过 SQL 查询从我们的 ERP 获取产品数据,由此返回的数据在大小级别非常平坦。一个产品有 3 个级别: 风格 颜色 尺寸 一种款式有多种颜色,一种颜色有多种尺码。 我创建了以下模型: publ
我正在尝试展开一些 json 数据。如果我像下面这样使用我的测试数据,一切正常! var data = [ { "title": 1, "parentids": [0] }, { "title
我希望使用 SceneKit 在 Swift 中的 3D 空间中绘制多个平面。具体来说,这些表面都将位于双曲面内。我以前从未绘制过自定义形状/对象,而且在尝试理解文档时我已经迷失了方向。 关于在 3D
预先感谢您阅读我的问题。我对 ARKit 非常陌生,并且已经学习了几个教程,这些教程向我展示了如何使用平面检测以及如何为平面使用不同的纹理。这个功能真的很棒,但这是我的问题。玩家是否可以先将飞机放置在
我正在阅读下面的源代码,我想知道我到底为什么要使用平面图方式。正如我所看到的,与通过 if 语句进行简单的 null 检查相比,实例化了更多的对象,执行了更多代码,这将在第一个 null 时终止,而不
我正在编写一个 Rails 应用程序并使用 Flat UI 进行样式设置。我目前正在将 flatui-rails gem 与 twitter-bootstrap-rails gem 结合使用。一切正常
我在维基百科中找到了射线平面相交代码的解决方案,该解决方案有效,我只是在其中求解线性方程组。 后来我找到了一些点到平面投影的代码,显然实现方式不同,并且在特定条件下也会产生不同的解决方案。 但是,我并
我正在使用 http://designmodo.github.io/Flat-UI/ 中的扁平 UI 我复制了复选框示例页面中的所有文件和代码。 但是我注意到该复选框并未显示为样式复选框,但在我单击初
这个问题已经有答案了: True Isometric Projection with HTML5 Canvas (3 个回答) 已关闭 7 年前。 我想创建一个等轴测图。该 map 存在等距矩形,如图
http://designmodo.github.io/Flat-UI/ 我想创建一个 Css 下拉菜单,我已经完成了下拉部分,但是我似乎无法模拟转换,也不知道如何编写这些代码。这是我目前所知道的,在
我是一名优秀的程序员,十分优秀!