为什么在导入 UTF-8 平面文件时 SSIS 无法识别换行符 {LF} 行分隔符?

发布于 2024-11-14 17:17:47 字数 722 浏览 6 评论 0 原文

我正在尝试使用 SSIS 将数据从 utf-8 编码的平面文件导入到 SQL Server 2008 中。这是行数据末尾在 Notepad++ 中的样子:

在此处输入图像描述

我还有几张图像显示了内容文件连接管理器如下所示:

在此处输入图像描述

在此处输入图像描述

您可以看到数据在文件连接管理器预览中正确显示。当我尝试导入此数据时,没有导入任何行。我收到一条错误消息,指示未找到行分隔符。您可以在文件连接管理器图像中看到标题行分隔符和行分隔符都设置为 {LF}。这足以生成正确的预览,所以我不明白为什么它无法导入。我尝试了很多带来零结果的方法:

  • 尝试使用 SSMS 中的向导导入...相同的结果
  • 尝试使用数据转换,没有影响
  • 尝试将行分隔符设置为 (0a),相同的结果

[平面文件源 [582]] 警告: 已到达数据文件末尾 读取标题行。确保 标题行分隔符和行数 要跳过的标题行是正确的。

感谢您查看此内容,我非常感谢您提供的任何帮助。

I am trying to import data from a utf-8 encoded flat file into SQL Server 2008 using SSIS. This is what the end of the row data looks like in Notepad++:

enter image description here

I have a couple more images showing what the file connection manager looks like:

enter image description here

enter image description here

You can see that the data shows correctly in the file connection manager preview. When I try to import this data, no rows import. I get an error message indicating that the row delimiter was not found. You can see in the file connection manager images that the header row delimiter and the row delimiter are both set to {LF}. This was sufficient to generate the correct preview, so I am lost to why it did not work to import. I have tried a number of things that have brought zero results:

  • Tried using the Wizard import in SSMS...same results
  • Tried using data conversion, no impact
  • Tried setting the row delimiter to (0a), same results

[Flat File Source [582]] Warning: The
end of the data file was reached while
reading header rows. Make sure the
header row delimiter and the number of
header rows to skip are correct.

Thanks for looking at this and I really appreciate any help you can offer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

老子叫无熙 2024-11-21 17:17:47

原因:

由于列分隔符 Ç"c" with cedilla)和 ,SSIS 无法读取文件并显示以下警告>不是,因为行分隔符{LF}换行)。

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

下面是一个示例 SSIS 包,展示了如何使用脚本组件解决问题,最后还有另一个示例来模拟您的问题。

解决方案:

以下示例包是用 SSIS 2008 R2 编写的。它读取带有行分隔符 {LF} 的平面文件作为单个列值;然后使用脚本组件分割数据,将信息插入到SQL Server 2008 R2数据库的表中。

使用 Notepad++ 创建一个包含几行的简单平面文件。下面的示例文件每行都有产品 ID标价信息,以 Ç 作为列分隔符分隔,并且每个行以 {LF} 分隔符结尾。

平面文件源

在 Notepad++ 上,单击编码,然后单击以 UTF-8 编码,以 UTF-8 编码保存平面文件。

Encoding UTF-8

该示例将使用名为 < 的 SQL Server 2008 R2 数据库代码>索拉。使用下面给定的脚本创建一个名为 dbo.ProductListPrice 的新表。 SSIS 会将平面文件数据插入到该表中。

USE Sora;
GO

CREATE TABLE dbo.ProductListPrice
(
        ProductId   nvarchar(30)    NOT NULL
    ,   ListPrice   numeric(12,2)   NOT NULL
);
GO

使用 Business Intelligence Development Studio (BIDS) 2008 R2 创建 SSIS 包。将包命名为 SO_6268205.dtsx。创建名为 Sora.ds 的数据源,以连接到 SQL Server 2008 R2 中的数据库 Sora

右键单击包内的任意位置,然后单击变量以查看变量窗格。在包范围 SO_6268205< 中创建一个名为 ColumnDelimiter 的新变量,其数据类型为 String /code> 并将变量设置为值 Ç

“包变量”

右键单击连接管理器并单击新建平面文件连接...创建连接以读取平面文件。

平面文件连接

常规 页面平面文件连接管理器编辑器,执行以下操作:

  • 连接管理器名称设置为ProductListPrice
  • 设置描述 > 至 平面文件连接管理器读取产品标价信息。
  • 选择平面文件路径。我的文件位于路径 C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt
  • 选择 {LF}< /strong> 来自标题行分隔符
  • 检查第一个数据行中的列名称
  • 单击

平面文件连接管理器编辑器 - 常规

Columns 页面上em>平面文件连接管理器编辑器,验证列分隔符为空且已禁用。单击高级页面。

平面文件连接管理器编辑器 - 列

高级页面上在平面文件连接管理器编辑器中,执行以下操作。

  • 名称设置为LineData
  • 验证列分隔符是否设置为{LF}
  • DataType 设置为 Unicode 字符串 [DT_WSTR]
  • OutputColumnWidth 设置为 < em>255
  • 单击预览页面。

平面文件连接管理器编辑器 - 高级

预览页面上在平面文件连接管理器编辑器中,验证显示的数据是否正确,然后单击确定

平面文件连接管理器编辑器 - 预览

您将看到数据源 Sora 和平面文件连接包底部的连接管理器选项卡上的ProductListPrice管理器。

Connection Managers

数据流任务拖放到控制流上包的选项卡并将其命名为文件到数据库 - 没有 Cedilla 分隔符

“数据流任务

双击数据流任务将视图切换到包上的数据流选项卡。将平面文件源拖放到数据流选项卡上。双击平面文件源以打开平面文件源编辑器

平面文件源编辑器连接管理器页面上,选择平面文件连接管理器 ProductListPrice 并单击页面。

平面文件源编辑器 - 连接管理器

页面上在平面文件源编辑器中,选中LineData列,然后单击确定

平面文件源编辑器 - 列

拖放脚本组件平面文件源下方的数据流选项卡上,选择转换,然后单击确定。将绿色箭头从平面文件源连接到脚本组件。双击脚本组件打开脚本转换编辑器

单击“脚本转换编辑器”上的“输入列”,然后选择“LineData”列。单击“输入和输出”页面。

脚本转换编辑器 - 输入列

输入和输出页面上在脚本转换编辑器中,执行以下操作。

  • 将输入名称更改为 FlatFileInput
  • 将输出名称更改为 SplitDataOutput
  • 选择输出列,然后单击添加列 。再次重复此操作以添加另一列。
  • 将第一列命名为 ProductId
  • ProductId 列的 DataType 设置为 Unicode 字符串 [DT_WSTR ]
  • 长度设置为30

脚本转换编辑器 - 输入和输出 - ProductId

脚本转换编辑器输入和输出页面上,执行以下操作。

  • 将第二列命名为 ListPrice
  • ListPrice 列的 DataType 设置为 数字 [DT_NUMERIC]
  • 精度设置为12
  • 比例设置为2
  • 点击脚本页面修改脚本

脚本转换编辑器 - 输入和输出 - ListPrice

>脚本转换编辑器脚本页面,执行以下操作。

  • 单击ReadOnlyVariables旁边的省略号按钮,然后选择变量User::ColumnDelimiter
  • 单击编辑脚本...

Script Transformation Editor - Script

将以下 C# 粘贴到脚本编辑器中。该脚本执行以下任务。

  • 使用变量 User::ColumnDelimiter 中定义的列分隔符值 Ç,方法FlatFileInput_ProcessInputRow< /em> 拆分传入值并将其分配给脚本组件转换中定义的两个输出列。

C# 脚本组件代码

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void PreExecute()
    {
        base.PreExecute();
    }

    public override void PostExecute()
    {
        base.PostExecute();
    }

    public override void FlatFileInput_ProcessInputRow(FlatFileInputBuffer Row)
    {
        const int COL_PRODUCT = 0;
        const int COL_PRICE = 1;

        char delimiter = Convert.ToChar(this.Variables.ColumnDelimiter);
        string[] lineData = Row.LineData.ToString().Split(delimiter);

        Row.ProductId = String.IsNullOrEmpty(lineData[COL_PRODUCT]) 
                            ? String.Empty 
                            : lineData[COL_PRODUCT];

        Row.ListPrice = String.IsNullOrEmpty(lineData[COL_PRICE]) 
                            ? 0 
                            : Convert.ToDecimal(lineData[COL_PRICE]);
    }
}

脚本组件代码 - C#

拖放 OLE DB 目标 数据流选项卡。将绿色箭头从脚本组件连接到OLE DB 目标。双击OLE DB 目标 打开OLE DB 目标编辑器

OLE DB 目标编辑器连接管理器 页面上,执行以下操作。

  • OLE DB 连接管理器中选择Sora
  • 表或视图 - 快速加载中选择数据访问模式
  • 表或视图的名称中选择[dbo].[ProductListPrice]
  • 单击 >映射页面

OLE DB 目标编辑器 - 连接管理器

单击 OLE DB 目标编辑器上的 Mappings 页面如果输入和输出列名称相同,em> 将自动映射列。单击确定

OLE DB Destination Editor - Mappings

配置所有组件后,数据流选项卡应如下所示。

Data Flow tab

在 SQL Server 中执行查询 select * from dbo.ProductListPrice Management Studio (SSMS) 查找表中的行数。在执行包之前它应该是空的。

包执行前表中的行

执行包。您将注意到该包已成功处理 9 行。该平面文件包含 10 行,但第一行是带有列名称的标题。

Packageexecution without delimiter

在 SQL 中执行查询 select * from dbo.ProductListPrice Server Management Studio (SSMS) 查找已成功插入表中的 9 行。数据应与平面文件数据匹配。

Rows in table after packageexecution

上面的示例说明了如何使用脚本组件手动拆分数据因为平面文件连接管理器在配置列分隔符Ç时遇到错误问题

模拟:

此示例显示了一个单独的平面文件连接管理器 配置了列分隔符Ç,执行但遇到警告并且不处理任何行。

右键单击连接管理器,然后单击新建平面文件连接...以创建要读取的连接平面文件。在平面文件连接管理器编辑器的常规页面上,执行以下操作:

  • 连接管理器名称设置为ProductListPrice_Cedilla
  • 将说明设置为带有 Cedilla 列分隔符的平面文件连接管理器。
  • 我的路径中有该文件C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt 选择平面文件路径。
  • 标题行分隔符中选择{LF}
  • 检查第一个数据行中的列名称
  • 单击页面

关于平面文件连接管理器编辑器的页面,执行以下操作:

  • 行分隔符设置为 {LF}
  • 列分隔符字段可能被禁用。单击重置列
  • 列分隔符设置为Ç
  • 单击高级页面

img src="https://i.sstatic.net/Dxxjz.png" alt="平面文件连接管理器编辑器 - 带 Cedilla - Columns">

< 平面文件连接管理器编辑器高级页面,执行以下操作:

  • 名称设置为 ProductId
  • ColumnDelimiter设置为Ç
  • DataType设置为< em>Unicode 字符串 [DT_WSTR]
  • 设置长度30
  • 点击列ListPrice

平面文件连接管理器编辑器 - 带 Cedilla - 高级 - ProductId

平面文件连接管理器编辑器<的高级页面上< /em>,执行以下操作:

  • 设置名称ListPrice
  • ColumnDelimiter设置为{LF}
  • DataType设置为数字[DT_NUMERIC]
  • DataPrecision设置为12< /code>
  • 设置DataScale2
  • 单击确定

平面文件连接管理器编辑器 - 带 Cedilla - 高级 - ListPrice

数据流任务拖放到控制流 选项卡并将其命名为 文件到数据库 -使用 Cedilla 分隔符。禁用第一个数据流任务。

Data Flow Task 2

使用平面文件源配置第二个数据流任务OLE DB 目标

数据流选项卡 - 2

双- 单击平面文件源以打开平面文件源编辑器。在平面文件源编辑器连接管理器页面上,选择平面文件连接管理器 ProductListPrice_Cedilla 并单击页面以配置列。单击确定

平面文件源编辑器 - Cedilla

执行包。所有组件将显示绿色,表示该过程成功,但不会处理任何行。您可以看到 平面文件源OLE DB 目标 之间没有行号指示

Package Execution - Cedilla

单击进度选项卡,您将注意到以下警告信息。

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

进度警告消息

Cause:

SSIS fails to read the file and displays the below warning due to the column delimiter Ç ("c" with cedilla) and not due to the line delimiter {LF} (Line Feed).

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

Here is a sample SSIS package that shows how to resolve the issue using Script Component and at the end there is another example that simulates your issue.

Resolution:

Below sample package is written in SSIS 2008 R2. It reads a flat file with row delimiter {LF} as a single column value; then splits the data using Script Component to insert the information into a table in SQL Server 2008 R2 database.

Use Notepad++ to create a simple flat file with few rows. The below sample file has Product Id and List Price information on each row separated by Ç as column delimiter and each row ends with {LF} delimiter.

Flat file source

On the Notepad++, click Encoding and then click Encoding in UTF-8 to save the flat file in UTF-8 encoding.

Encoding UTF-8

The sample will use an SQL Server 2008 R2 database named Sora. Create a new table named dbo.ProductListPrice using the below given script. SSIS will insert the flat file data into this table.

USE Sora;
GO

CREATE TABLE dbo.ProductListPrice
(
        ProductId   nvarchar(30)    NOT NULL
    ,   ListPrice   numeric(12,2)   NOT NULL
);
GO

Create an SSIS package using Business Intelligence Development Studio (BIDS) 2008 R2. Name the package as SO_6268205.dtsx. Create a data source named Sora.ds to connect to the database Sora in SQL Server 2008 R2.

Right-click anywhere inside the package and then click Variables to view the variables pane. Create a new variable named ColumnDelimiter of data type String in the package scope SO_6268205 and set the variable with the value Ç

Package variables

Right-click on the Connection Managers and click New Flat File Connection... to create a connection to read the flat file.

Flat File Connection

On the General page of the Flat File Connection Manager Editor, perform the following actions:

  • Set Connection manager name to ProductListPrice
  • Set Description to Flat file connection manager to read product list price information.
  • Select the flat file path. I have the file in the path C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt
  • Select {LF} from Header Row Delimiter
  • Check Column names in the first data row
  • Click Columns page

Flat File Connection Manager Editor - General

On the Columns page of the Flat File Connection Manager Editor, verify that the Column delimiter is blank and disabled. Click Advanced page.

Flat File Connection Manager Editor - Columns

On the Advanced page of the Flat File Connection Manager Editor, perform the following actions.

  • Set the Name to LineData
  • Verify that the Column delimiter is set to {LF}
  • Set the DataType to Unicode string [DT_WSTR]
  • Set the OutputColumnWidth to 255
  • Click the Preview page.

Flat File Connection Manager Editor - Advanced

On the Preview page of the Flat File Connection Manager Editor, verify that the displayed data looks correct and click OK.

Flat File Connection Manager Editor - Preview

You will see the data source Sora and the flat file connection manager ProductListPrice on the Connection Managers tab at the bottom of the package.

Connection Managers

Drag and drop Data Flow Task onto the Control Flow tab of the package and name it as File to database - Without Cedilla delimiter

Data Flow Task 1

Double-click the Data Flow Task to switch the view to the Data Flow tab on the package. Drag and drop a Flat File Source on the Data Flow tab. Double-click the Flat File Source to open Flat File Source Editor.

On the Connection Manager page of the Flat File Source Editor, select the Flat File Connection Manager ProductListPrice and click Columns page.

Flat File Source Editor - Connection Manager

On the Columns page of the Flat File Source Editor, check the column LineData and click OK.

Flat File Source Editor - Columns

Drag and drop a Script Component onto the Data Flow tab below the Flat File Source, select Transformation and click OK. Connect the green arrow from Flat File Source to Script Component. Double-click Script Component to open Script Transformation Editor.

Click Input Columns on Script Transformation Editor and select LineData column. Click Inputs and Outputs page.

Script Transformation Editor - Input Columns

On the Inputs and Outputs page of the Script Transformation Editor, perform the following actions.

  • Change the inputs name to FlatFileInput
  • Change the outputs name to SplitDataOutput
  • Select Output Columns and click Add Column. Repeat this again to add another column.
  • Name the first column ProductId
  • Set the DataType of column ProductId to Unicode string [DT_WSTR]
  • Set the Length to 30

Script Transformation Editor - Inputs and Outputs - ProductId

On the Inputs and Outputs page of the Script Transformation Editor, perform the following actions.

  • Name the second column ListPrice
  • Set the DataType of column ListPrice to numeric [DT_NUMERIC]
  • Set the Precision to 12
  • Set the Scale to 2
  • Click Script page to modify the script

Script Transformation Editor - Inputs and Outputs - ListPrice

On the Script page of the Script Transformation Editor, perform the following actions.

  • Click the ellipsis button against ReadOnlyVariables and select the variable User::ColumnDelimiter
  • Click Edit Script...

Script Transformation Editor - Script

Paste the below C# in the Script Editor. The script performs the following tasks.

  • Using the column delimiter value Ç defined in the variable User::ColumnDelimiter, the method FlatFileInput_ProcessInputRow splits the incoming value and assigns it to the two output columns defined in the Script Component transformation.

Script component code in C#

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void PreExecute()
    {
        base.PreExecute();
    }

    public override void PostExecute()
    {
        base.PostExecute();
    }

    public override void FlatFileInput_ProcessInputRow(FlatFileInputBuffer Row)
    {
        const int COL_PRODUCT = 0;
        const int COL_PRICE = 1;

        char delimiter = Convert.ToChar(this.Variables.ColumnDelimiter);
        string[] lineData = Row.LineData.ToString().Split(delimiter);

        Row.ProductId = String.IsNullOrEmpty(lineData[COL_PRODUCT]) 
                            ? String.Empty 
                            : lineData[COL_PRODUCT];

        Row.ListPrice = String.IsNullOrEmpty(lineData[COL_PRICE]) 
                            ? 0 
                            : Convert.ToDecimal(lineData[COL_PRICE]);
    }
}

Script Component Code - C#

Drag and drop OLE DB Destination onto the Data Flow tab. Connect the green arrow from Script Component to OLE DB Destination. Double-click OLE DB Destination to open OLE DB Destination Editor.

On the Connection Manager page of the OLE DB Destination Editor, perform the following actions.

  • Select Sora from OLE DB Connection Manager
  • Select Table or view - fast load from Data access mode
  • Select [dbo].[ProductListPrice] from Name of the table or the view
  • Click Mappings page

OLE DB Destination Editor - Connection Manager

Click Mappings page on the OLE DB Destination Editor would automatically map the columns if the input and output column names are same. Click OK.

OLE DB Destination Editor - Mappings

Data Flow tab should look something like this after configuring all the components.

Data Flow tab

Execute the query select * from dbo.ProductListPrice in the SQL Server Management Studio (SSMS) to find the number of rows in the table. It should be empty before executing the package.

Rows in table before package execution

Execute the package. You will notice that the package successfully processed 9 rows. The flat file contains 10 lines but the first row is header with column names.

Package execution without delimiter

Execute the query select * from dbo.ProductListPrice in the SQL Server Management Studio (SSMS) to find the 9 rows successfully inserted into the table. The data should match with flat file data.

Rows in table after package execution

The above example illustrated how to manually split the data using Script Component because the Flat File Connection Manager encounters error when configured the column delimiter Ç

Issue Simulation:

This example shows a separate Flat File Connection Manager configured with column delimiter Ç, which executes but encounters a warning and does not process any lines.

Right-click on the Connection Managers and click New Flat File Connection... to create a connection to read the flat file. On the General page of the Flat File Connection Manager Editor, perform the following actions:

  • Set Connection manager name to ProductListPrice_Cedilla
  • Set Description to Flat file connection manager with Cedilla column delimiter.
  • I have the file in the path C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt Select the flat file path.
  • Select {LF} from Header Row Delimiter
  • Check Column names in the first data row
  • Click Columns page

Flat File Connection Manager Editor - With Cedilla - General

On the Columns page of the Flat File Connection Manager Editor, perform the following actions:

  • Set Row delimiter to {LF}
  • The column delimiter field may be disabled. Click Reset Columns
  • Set Column delimiter to Ç
  • Click Advanced page

Flat File Connection Manager Editor - With Cedilla - Columns

On the Advanced page of the Flat File Connection Manager Editor, perform the following actions:

  • Set the Name to ProductId
  • Set the ColumnDelimiter to Ç
  • Set the DataType to Unicode string [DT_WSTR]
  • Set the Length to 30
  • Click column ListPrice

Flat File Connection Manager Editor - With Cedilla - Advanced - ProductId

On the Advanced page of the Flat File Connection Manager Editor, perform the following actions:

  • Set the Name to ListPrice
  • Set the ColumnDelimiter to {LF}
  • Set the DataType to numeric [DT_NUMERIC]
  • Set the DataPrecision to 12
  • Set the DataScale to 2
  • Click OK

Flat File Connection Manager Editor - With Cedilla - Advanced - ListPrice

Drag and drop a Data Flow task onto the Control Flow tab and name it as File to database - With Cedilla delimiter. Disable the first data flow task.

Data Flow Task 2

Configure the second data flow task with Flat File Source and OLE DB Destination

Data Flow Tab - 2

Double-click the Flat File Source to open Flat File Source Editor. On the Connection Manager page of the Flat File Source Editor, select the Flat File Connection Manager ProductListPrice_Cedilla and click Columns page to configure the columns. Click OK.

Flat File Source Editor - Cedilla

Execute the package. All the components will display green color to indicate that the process was success but no rows will be processed. You can see that there are no rows numbers indication between the Flat File Source and OLE DB Destination

Package Execution - Cedilla

Click the Progress tab and you will notice the following warning message.

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

Progress Warning message

禾厶谷欠 2024-11-21 17:17:47

上面的答案似乎非常复杂,只需转换文件 Rehashed 中的行结尾

Dim FileContents As String = My.Computer.FileSystem.ReadAllText("c:\Temp\UnixFile.csv")

Dim NewFileContents As String = FileContents.Replace(vbLf, vbCrLf)

My.Computer.FileSystem.WriteAllText("c:\temp\WindowsFile.csv", NewFileContents, False, New System.Text.UnicodeEncoding)

此处

Answer above seems awfully complicated, just convert the line endings in the file

Dim FileContents As String = My.Computer.FileSystem.ReadAllText("c:\Temp\UnixFile.csv")

Dim NewFileContents As String = FileContents.Replace(vbLf, vbCrLf)

My.Computer.FileSystem.WriteAllText("c:\temp\WindowsFile.csv", NewFileContents, False, New System.Text.UnicodeEncoding)

Rehashed from here

闻呓 2024-11-21 17:17:47

如果您尝试在 Windows 上通过 SSIS 使用在不同平台(如 Unix、Mac 等)上生成的 FlatFile,也会出现此问题

在这种情况下,您需要做的就是使用 unix2dos 命令将文件格式从 UNIX 转换为 DOS

unix2dos file-to-convert

This issue also arises if you are trying to consume FlatFile generated on a different platform like Unix, Mac etc via SSIS on windows

In such a scenario all you need to do is convert the file format from say UNIX to DOS with unix2dos command

unix2dos file-to-convert
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文