powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Microsoft.Jet.OLEDB.4.0" не зарегистрирован
25 сообщений из 54, страница 2 из 3
Период между сообщениями больше года.
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39121632
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Столкнулся с проблемой записи в DBF (нужно выгружать файл в заданном формате для сторонней конторы, а они его в свой 1С).
Приложение ANY.CPU, терминальный сервер 64бита, офис 2007 (32).
AccessDatabaseEngine_x64.exe не ставитс, т.к. офис 2007 и другого нет.

DotNetDBF.dll - пишет очень криво
А виндовые провайдеры не находятся, т.к. приложение 64, а провайдеры 32бита.

Правильно ли я понял что это тупик?
- Нет бесплатной сторонней либы под ANY.CPU способной писать в DBF.
- Первый вариант, ставить офис 2010 х64.
- Второй собирать проект под x86.


Пробовал
4 варианта
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
      private void button1_Click(object sender, EventArgs e)
      {
                  
         //var field1 = new DBFField { Name = "KONTR", DataType = NativeDbType.Char, FieldLength = 36 };
         //var field2 = new DBFField { Name = "NAME", DataType = NativeDbType.Char, FieldLength = 240 };
         //var field3 = new DBFField { Name = "INNKON", DataType = NativeDbType.Char, FieldLength = 12 };
         //var field4 = new DBFField { Name = "KPPKON", DataType = NativeDbType.Char, FieldLength = 9 };
         //var field5 = new DBFField { Name = "Y_ADDR", DataType = NativeDbType.Char, FieldLength = 250 };
         //var field6 = new DBFField { Name = "P_ADDR", DataType = NativeDbType.Char, FieldLength = 250 };
         //using (var writer = new DBFWriter("KONTR.DBF") { Fields = new[] { field1, field2, field3, field4, field5, field6 } })
         using (var writer = new DBFWriter("KONTR.DBF") { CharEncoding = Encoding.GetEncoding(1251) })
         {

            for (int i = 0; i < 1000; i++)
            {
               writer.WriteRecord(i.ToString(), Guid.NewGuid().ToString("n"), "", null, "", "");
            }
         }

      }

      private void button2_Click(object sender, EventArgs e)
      {
         OdbcConnection conn = new OdbcConnection(
            @"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq="+ Application.StartupPath + ";" );
         conn.Open();
         
         var c = conn.CreateCommand();
         c.CommandText = "insert into KONTR (KONTR, NAME, INNKON, KPPKON, Y_ADDR, P_ADDR) values (?,?,?,?,?,?)";
         c.Parameters.Add("code", OdbcType.VarChar, 36);
         c.Parameters.Add("name", OdbcType.VarChar, 240);
         c.Parameters.Add("inn", OdbcType.VarChar, 12);
         c.Parameters.Add("kpp", OdbcType.VarChar, 12);
         c.Parameters.Add("jAddress", OdbcType.VarChar, 250);
         c.Parameters.Add("fAddress", OdbcType.VarChar, 250);
         for (int i = 0; i < 1000; i++)
         {
            c.Parameters["code"].Value = "Йыв" + i.ToString();
            c.Parameters["name"].Value = Guid.NewGuid().ToString("n");
            c.Parameters["inn"].Value = "";
            c.Parameters["kpp"].Value = "";
            c.Parameters["jAddress"].Value = "";
            c.Parameters["fAddress"].Value = "";
            c.ExecuteNonQuery();
         }
         conn.Close();
      }

      private void button3_Click(object sender, EventArgs e)
      {
         OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + "; Extended Properties=dBASE IV;User ID=Admin;Password=;");
         conn.Open();

         var c = conn.CreateCommand();
         c.CommandText = "insert into KONTR (KONTR, NAME, INNKON, KPPKON, Y_ADDR, P_ADDR) values (?,?,?,?,?,?)";
         c.Parameters.Add("code", OleDbType.VarChar, 36);
         c.Parameters.Add("name", OleDbType.VarChar, 240);
         c.Parameters.Add("inn", OleDbType.VarChar, 12);
         c.Parameters.Add("kpp", OleDbType.VarChar, 12);
         c.Parameters.Add("jAddress", OleDbType.VarChar, 250);
         c.Parameters.Add("fAddress", OleDbType.VarChar, 250);
         for (int i = 0; i < 1000; i++)
         {
            c.Parameters["code"].Value ="Йыв" + i.ToString();
            c.Parameters["name"].Value = Guid.NewGuid().ToString("n");
            c.Parameters["inn"].Value = "";
            c.Parameters["kpp"].Value = "";
            c.Parameters["jAddress"].Value = "";
            c.Parameters["fAddress"].Value = "";
            c.ExecuteNonQuery();
         }
         conn.Close();
      }

      private void button4_Click(object sender, EventArgs e)
      {
         
         OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Application.StartupPath + ";Extended Properties=dBASE IV;User ID=Admin;");
         conn.Open();

         var c = conn.CreateCommand();
         c.CommandText = "insert into KONTR (KONTR, NAME, INNKON, KPPKON, Y_ADDR, P_ADDR) values (?,?,?,?,?,?)";
         c.Parameters.Add("code", OleDbType.VarChar, 36);
         c.Parameters.Add("name", OleDbType.VarChar, 240);
         c.Parameters.Add("inn", OleDbType.VarChar, 12);
         c.Parameters.Add("kpp", OleDbType.VarChar, 12);
         c.Parameters.Add("jAddress", OleDbType.VarChar, 250);
         c.Parameters.Add("fAddress", OleDbType.VarChar, 250);
         for (int i = 0; i < 1000; i++)
         {
            c.Parameters["code"].Value = "Йыв" + i.ToString();
            c.Parameters["name"].Value = Guid.NewGuid().ToString("n");
            c.Parameters["inn"].Value = "";
            c.Parameters["kpp"].Value = "";
            c.Parameters["jAddress"].Value = "";
            c.Parameters["fAddress"].Value = "";
            c.ExecuteNonQuery();
         }
         conn.Close();
      }
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39121875
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
barrabasСтолкнулся с проблемой записи в DBF (нужно выгружать файл в заданном формате для сторонней конторы, а они его в свой 1С).
Может легче договорится с той конторой об обмене данными через XML?
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39121895
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2,

Ну у них разговор простой, у нас есть процедура загрузки, она работает, давайте нам в неё нужный файл.
Не уверен что на их стороне есть разработчики вообще.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39121982
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
barrabas,

Попробуйте драйвера для VPF (Visual Fox Pro). Обычно помогало.

Так же вроде можно сделать таблицу в mdb и оттуда конвертировать в DBF
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39121988
Фотография Владимир СА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2barrabas,

Попробуйте драйвера для VPF (Visual Fox Pro). Обычно помогало.

Так же вроде можно сделать таблицу в mdb и оттуда конвертировать в DBFДа и вообще... поставить VFP 9.0 и на нем прогу сварганить...?
Не подходит ?
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122307
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2barrabas,

Попробуйте драйвера для VPF (Visual Fox Pro). Обычно помогало.

Так же вроде можно сделать таблицу в mdb и оттуда конвертировать в DBF
да не, на foxpro теже 32 битные дрова и судя по форуму те-же пляски вокруг ODBC на x64.

64битное приложение не увидит 32битные дрова хоть убейся похоже.

Думаю о варианте, написать маленькую 32битную консольную в которую на входящий поток будут слаться команды (типа вставь запись, открой соединения и т.д.). Эта программа будет лежать в папке приложения, когда надо, основное приложение запустит этот 32битный процесс, и будет слать туда инфу которую нужно сохранить в dbf, а потом закроет его (ну и само тоже чтоб закрывалось после 5 минут бездействия, если вдруг основное приложение рухнет, чтоб не засирался терминальный сервер).
Просто собирать весь проект под х86 еще хуже вариант, у кучи людей стоят 64битные клиенты оракла (у тех что не через терминал работаю). а офиса нет 2010
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122322
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasCat2barrabas,

Попробуйте драйвера для VPF (Visual Fox Pro). Обычно помогало.

Так же вроде можно сделать таблицу в mdb и оттуда конвертировать в DBF
да не, на foxpro теже 32 битные дрова и судя по форуму те-же пляски вокруг ODBC на x64.

64битное приложение не увидит 32битные дрова хоть убейся похоже.

Думаю о варианте, написать маленькую 32битную консольную в которую на входящий поток будут слаться команды (типа вставь запись, открой соединения и т.д.). Эта программа будет лежать в папке приложения, когда надо, основное приложение запустит этот 32битный процесс, и будет слать туда инфу которую нужно сохранить в dbf, а потом закроет его (ну и само тоже чтоб закрывалось после 5 минут бездействия, если вдруг основное приложение рухнет, чтоб не засирался терминальный сервер).
Просто собирать весь проект под х86 еще хуже вариант, у кучи людей стоят 64битные клиенты оракла (у тех что не через терминал работаю). а офиса нет 2010
или написать прогу конвертер xml в нужный pdf, пользователь выбирает в основном приложении параметры для формирования, приложение лезет в базу, формирует xml, запускает x86-приложение-конвертер, ждет результата, удаляет xml.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122386
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2barrabasСтолкнулся с проблемой записи в DBF (нужно выгружать файл в заданном формате для сторонней конторы, а они его в свой 1С).
Может легче договорится с той конторой об обмене данными через XML?
легче писать dbf без использования кривых провайдеров и библиотек.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122392
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть еще такая штука Не пользовался. Как понял читает/пишет DBF напрямую из/в файл без доп.драйверов
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122439
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилCat2пропущено...

Может легче договорится с той конторой об обмене данными через XML?
легче писать dbf без использования кривых провайдеров и библиотек.
ну в принципе описание формата не сложное.
но не хочется заниматься еще и этой хернёй.
особенно в таком вопросе, нужно то просто выгрузить по кнопке в файлы. причем этот функционал работал, но сейчас идет загон юзеров в терминалку, она сама x64 т.к. 2008, а офис 32 т.к. 1С что-то тоже там формирует.
Получается что отваливается функционал к которому возвращаться я не планировал вообще :(
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122440
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЕсть еще такая штука Не пользовался. Как понял читает/пишет DBF напрямую из/в файл без доп.драйверов
спасибо, посмотрю
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122441
Фотография Владимир СА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasИзопропилпропущено...

легче писать dbf без использования кривых провайдеров и библиотек.
ну в принципе описание формата не сложное.
но не хочется заниматься еще и этой хернёй.

особенно в таком вопросе, нужно то просто выгрузить по кнопке в файлы. причем этот функционал работал, но сейчас идет загон юзеров в терминалку, она сама x64 т.к. 2008, а офис 32 т.к. 1С что-то тоже там формирует.
Получается что отваливается функционал к которому возвращаться я не планировал вообще :(Дык, один раз сделать... и только кнопку жать...
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122607
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasDima TЕсть еще такая штука Не пользовался. Как понял читает/пишет DBF напрямую из/в файл без доп.драйверов
спасибо, посмотрю
Не пишет русскую кодировку. пробовал, и 1251, и 866.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122610
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир САbarrabasпропущено...

ну в принципе описание формата не сложное.
но не хочется заниматься еще и этой хернёй.

особенно в таком вопросе, нужно то просто выгрузить по кнопке в файлы. причем этот функционал работал, но сейчас идет загон юзеров в терминалку, она сама x64 т.к. 2008, а офис 32 т.к. 1С что-то тоже там формирует.
Получается что отваливается функционал к которому возвращаться я не планировал вообще :(Дык, один раз сделать... и только кнопку жать...
Даже делать не пришлось.
Нашел код, рабочий . Осталось поправить под себя.
Хочу сделать все-таки типа построчного писателя. Загонять тысячи строк в datatable а потом только их писать, как-то не гуманно. Нужно датаридер построчно обслуживать.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122821
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можешь мою поделку потестить
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
using System.IO;
using System.Diagnostics;

namespace ConsoleApplication1 {
    // Информация о поле
    sealed class DbfColumn {
        public readonly String name;
        public readonly Char type;
        public readonly Byte size;
        public readonly Byte digs;
        public readonly Int32 offset;

        public DbfColumn(String name, Char type, Byte size = 0, Byte digs = 0, Int32 offset = 0) {
            // Проверка имени поля
            if (name.Length > 10) throw new ApplicationException("DBF: Превышение размера (10 символов) имени поля: " + name);
            for (Int32 i = 0; i < name.Length; i++) {
                Char c = name[i];
                if(Char.IsLower(c)) {
                    name = name.ToUpper();
                }
                if (!Char.IsLetterOrDigit(c) && c != '_') throw new ApplicationException("DBF: Имя поля должно содержать только буквы и цифры " + name);
            }
            // Проверка типа
            type = Char.ToUpper(type);
            switch(type) {
                case 'D':
                    size = 8;
                    digs = 0;
                    break;
                case 'L':
                    size = 1;
                    digs = 0;
                    break;
                case 'I':
                    size = 4;
                    digs = 0;
                    break;
                case 'C':
                    digs = 0;
                    break;
                case 'N':
                    if (digs < 0 || (digs > 0 && digs + 2 > size)) throw new ApplicationException("DBF: Неверное кол-во знаков после запятой в поле: " + name);
                    break;
                default:
                    throw new ApplicationException(String.Format("DBF: Неверный тип поля {0}({1})", name, type));
            }
            // Проверка размера
            if (size <= 0) throw new ApplicationException("DBF: Не задан размер поля " + name);
           
            this.name = name;
            this.type = type;
            this.size = size;
            this.digs = digs;
            this.offset = offset;
        }

        public DbfColumn(DbfColumn col, Int32 offset) {
            this.name = col.name;
            this.type = col.type;
            this.size = col.size;
            this.digs = col.digs;
            this.offset = offset;
        }

        public override string ToString() {
            var sb = new StringBuilder();
            sb.Append(name);
            sb.Append(" ");
            sb.Append(type);
            if(type == 'N' || type == 'C') {
                sb.Append("(");
                sb.Append(size.ToString());
                if(digs != 0) {
                    sb.Append(",");
                    sb.Append(digs.ToString());
                }
                sb.Append(")");
            }
            return sb.ToString();
        }
    }

    //**************************************************************************
    // Запись DBF
    class DbfWriter : IDisposable{
        DbfColumn[] fields; // Названия полей
        Byte[] row; // Текущая строка
        Int32 row_size; // Размер строки
        Int32 row_count = 0; // Кол-во строк
        Encoding encoder; // Перекодировщик
        FileStream fs;
        String file_name;

        public DbfWriter(DbfColumn[] field_list, String file, Int32 code_page = 1251) {
            fields = new DbfColumn[field_list.Length];
            Int32 offset = 0;
            for(Int32 i = 0; i < field_list.Length; i++) {
                fields[i] = new DbfColumn(field_list[i], offset);
                offset += field_list[i].size;
            }
            row_size = offset;
            row = new Byte[row_size];
            for (Int32 i = 0; i < row.Length; i++) row[i] = 32;
            encoder = Encoding.GetEncoding(code_page);
            fs = new FileStream(file, FileMode.Create, FileAccess.Write);
            fs.Position = 32 + 32 * fields.Length + 1;
            file_name = file;
        }

        // Запись String в поле текущей записи
        public void Set(Int32 col_num, String value) {
            var f = fields[col_num];
            if(f.type != 'C') throw new ApplicationException("DBF: неверный тип поля " + f.ToString());
            Byte[] s = encoder.GetBytes(value);
            if(s.Length > f.size) s = s.Take(f.size).ToArray();
            s.CopyTo(row, f.offset);
        }

        // Запись Int32 в поле текущей записи
        public void Set(Int32 col_num, Int32 value) {
            var f = fields[col_num];
            if (f.type == 'N') {
                Boolean minus = (value < 0);
                if (minus) value = -value;
                Int32 offset = f.offset + f.size - (f.digs == 0 ? 1 : f.digs + 2);
                for (; value >= 10 && offset > f.offset; offset--) {
                    row[offset] = (Byte)(value % 10 + 48);
                    value /= 10;
                }
                if (value >= 10) throw new ApplicationException("DBF: превышение размера поля " + f.ToString());
                row[offset] = (Byte)(value + 48);
                if(minus) {
                    offset--;
                    if (offset < f.offset) throw new ApplicationException("DBF: превышение размера поля " + f.ToString());
                    row[offset] = 45; // '-'
                }
                if (f.digs > 0) {
                    offset = f.offset + f.size - f.digs - 1;
                    row[offset] = 46; // '.'
                    offset++;
                    for (; offset < f.offset + f.size; offset++) row[offset] = 48; // '0'
                }
            } else if (f.type == 'I') {
                row[f.offset] = (Byte)(value & 0xFF);
                row[f.offset + 1] = (Byte)((value >> 8) & 0xFF);
                row[f.offset + 2] = (Byte)((value >> 16) & 0xFF);
                row[f.offset + 3] = (Byte)((value >> 24) & 0xFF);
            } else {
                throw new ApplicationException("DBF: неверный тип поля " + f.ToString());
            }
        }

        // Запись Double в поле текущей записи
        public void Set(Int32 col_num, Double value) {
            var f = fields[col_num];
            if (f.type != 'N') throw new ApplicationException("DBF: неверный тип поля " + f.ToString());
            Boolean minus = (value < 0);
            if (minus) value = -value;
            switch (f.digs) {
                case 0:
                    value += 0.5;
                    break;
                case 1:
                    value += 0.05;
                    break;
                case 2:
                    value += 0.005;
                    break;
                default:
                    Double add = 0.0005;
                    for (Int32 i = 3; i < f.digs; i++) add /= 10;
                    value += add;
                    break;
            }
            Int32 val = (Int32)value;
            value -= val;
            Int32 offset = f.offset + f.size - (f.digs == 0 ? 1 : f.digs + 2);
            for (; val >= 10 && offset > f.offset; offset--) {
                row[offset] = (Byte)(val % 10 + 48);
                val /= 10;
            }
            if (val >= 10) throw new ApplicationException("DBF: превышение размера поля " + f.ToString());
            row[offset] = (Byte)(val + 48);
            if (minus) {
                offset--;
                if (offset < f.offset) throw new ApplicationException("DBF: превышение размера поля " + f.ToString());
                row[offset] = 45; // '-'
            }
            if (f.digs > 0) {
                offset = f.offset + f.size - f.digs - 1;
                row[offset] = 46; // '.'
                offset++;

                for (; offset < f.offset + f.size; offset++) {
                    value *= 10;
                    val = (Int32)value;
                    row[offset] = (Byte)(val + 48);
                    value -= val;
                }
            }
        }

        // Запись DateTime в поле текущей записи
        public void Set(Int32 col_num, DateTime value) {
            var f = fields[col_num];
            if (f.type != 'D') throw new ApplicationException("DBF: неверный тип поля " + f.ToString());
            if (value.Year > 1) {
                Int32 x = value.Year;
                row[f.offset + 3] = (Byte)(x % 10 + 48);
                x /= 10;
                row[f.offset + 2] = (Byte)(x % 10 + 48);
                x /= 10;
                row[f.offset + 1] = (Byte)(x % 10 + 48);
                x /= 10;
                row[f.offset + 0] = (Byte)(x % 10 + 48);
                x = value.Month;
                row[f.offset + 5] = (Byte)(x % 10 + 48);
                x /= 10;
                row[f.offset + 4] = (Byte)(x % 10 + 48);
                x = value.Day;
                row[f.offset + 7] = (Byte)(x % 10 + 48);
                x /= 10;
                row[f.offset + 6] = (Byte)(x % 10 + 48);
            }
        }

        // Запись Boolean в поле текущей записи
        public void Set(Int32 col_num, Boolean value) {
            var f = fields[col_num];
            if (f.type != 'L') throw new ApplicationException("DBF: неверный тип поля " + f.ToString());
            row[f.offset] = (Byte)(value ? 84 : 70); // 'T' 'F'
        }

        // Сохранение текущей записи
        public void StoreRow() {
            row_count++;
            fs.WriteByte(32);
            fs.Write(row, 0, row_size);
            for (Int32 i = 0; i < row.Length; i++) row[i] = 32;
        }

        public void Dispose() {
            if (fs != null) {
                fs.Close();
                fs = null;
                File.Delete(file_name);
            }
        }

        public void Close() {
            if (fs == null) return;
            fs.Position = 0;
            // Заголовок
            var buf = new Byte[32];
            buf[0] = 0x03; //  	dBASE III, dBASE IV, dBASE 5, dBASE 7, FoxPro, FoxBASE+
            buf[1] = (Byte)(DateTime.Today.Year - 1900); // Дата последней модификации в виде ГГММДД
            buf[2] = (Byte)(DateTime.Today.Month);
            buf[3] = (Byte)(DateTime.Today.Day);
            buf[4] = (Byte)(row_count & 0xFF); // Число записей в базе 
            buf[5] = (Byte)((row_count >> 8) & 0xFF);
            buf[6] = (Byte)((row_count >> 16) & 0xFF);
            buf[7] = (Byte)((row_count >> 24) & 0xFF);
            Int32 hdr = 32 + 32 * fields.Length + 1; // Полная длина заголовка (с дескрипторами полей)
            buf[8] = (Byte)(hdr & 0xFF);
            buf[9] = (Byte)((hdr >> 8) & 0xFF);
            buf[10] = (Byte)((row_size + 1) & 0xFF); // Длина одной записи
            buf[11] = (Byte)(((row_size + 1) >> 8) & 0xFF);
            buf[29] = (Byte)(encoder.CodePage == 866 ? 0x65 : 0xC9); // Кодовая страница
            fs.Write(buf, 0, 32);
            // Поля
            foreach (var f in fields) {
                for (Int32 i = 0; i < 32; i++) buf[i] = 0;
                System.Text.Encoding.Default.GetBytes(f.name).CopyTo(buf, 0); // Имя поля
                buf[11] = (Byte)f.type; // Тип поля
                buf[16] = (Byte)f.size; // Полная длина поля
                buf[17] = (Byte)f.digs; // Число десятичных разрядов
                fs.Write(buf, 0, 32);
            }
            fs.WriteByte(13);
            fs.Close();
            fs = null;
        }
    }

    //*******************************************************************************************************
    // Пример использования
    class Program {
        const Int32 TEST = 1000000;

        static void Main(string[] args) {
            var text = new String[100];
            for (Int32 i = 0; i < 100; i++) text[i] = "Текст " + i;
            Stopwatch sw = Stopwatch.StartNew();
            // Структура таблицы
            var cols = new DbfColumn[] { new DbfColumn("INT", 'I'), new DbfColumn("CHARASTER", 'C', 20), new DbfColumn("DATE", 'D'), new DbfColumn("NUMERIC", 'N', 10, 2), new DbfColumn("NUMERIC2", 'N', 10), new DbfColumn("LOGICAL", 'L') };
            // Создание таблицы (заголовок, имя файла, кодовая страница)
            using (var dbf = new DbfWriter(cols, "test.dbf", 866)) {
                // Заполнение 
                Double d = 0;
                for (Int32 i = 0; i < TEST; i++) {
                    // dbf.Set(Номер поля, значение)
                    dbf.Set(0, i);
                    dbf.Set(1, text[i % 100]);
                    dbf.Set(2, DateTime.Today);
                    dbf.Set(3, d);
                    dbf.Set(4, -i);
                    dbf.Set(5, i % 2 == 0);
                    dbf.StoreRow(); // Сохранение записи
                    d += 1.23;
                }
                dbf.Close(); // Сохранение файла (иначе удаляется)
            }
            Console.WriteLine("Записано " + TEST + " строк. Время " + sw.ElapsedMilliseconds + " мсек");
            Console.WriteLine("Press any key ...");
            Console.ReadKey();
        }
    }
}


По моим тестам 1 млн. записей меньше секунды пишет. Память не расходует, сборки мусора минимум.

Сделал для себя заготовку DBF писать с нуля. Тесты гонял - корректно пишет, результаты открываются в Visual FoxPro. В реальных проектах пока не использовал, т.к. пока только изучаю C#, до реального применения не все готово.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122878
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

Спасибо.
Тоже работает с 866.
А Fast DBF посмотрел, там заголовок файла от 3й версии, там даже нет указания ID языкового драйвера.
Ну так всегда бывает когда делают англоязычные товарищи. Помню в NPOI тоже слал баги связанные с десятичным разделителем в xml, они тупо не думают что бывают какие-то другие варианты, но там вроде оперативно ответили и дали патч.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122894
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

Только что-то не понял с типами. Для double и single вроде как F должен быть. А N для decimal, для которого нет перегрузки метода Set
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122919
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasDima T,

Только что-то не понял с типами. Для double и single вроде как F должен быть. А N для decimal, для которого нет перегрузки метода Set
Для DBF всегда стандартным был тип NUMERIC, т.е. N. Тип F - это экзотика которая мало где встречается (лично мне не попадалось). Т.е. в итоге числовые типы всегда должны быть N

Другой вопрос чем его представить внутри кода C#. Т.е. что давать на вход. С целыми понятно: Int32, а вот с дробными вопрос. Выбирал между decimal и double. Второй предпочтительнее оказался, т.к. этот тип процессор понимает, т.е. быстрее работает. Теоретически возможна проблема с точностью, но лично мне она не критична, т.к. double это точность 15 десятичных знаков - больше начинаются погрешности. Мне больше 10 никогда не надо, поэтому не критично если даже в расчетах поучаствуют.

Если надо - могу добавить Set(Int32 col_num, Decimal value). По большому счету одно из двух:
1. в Set(Int32 col_num, Double value) заменить Double на Decimal
2. Привести Decimal к Double и Set(Int32 col_num, Double value)

Надо только потестить как быстрее работать будет. Подозреваю что по варианту 2.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39122976
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TbarrabasDima T,

Только что-то не понял с типами. Для double и single вроде как F должен быть. А N для decimal, для которого нет перегрузки метода Set
Для DBF всегда стандартным был тип NUMERIC, т.е. N. Тип F - это экзотика которая мало где встречается (лично мне не попадалось). Т.е. в итоге числовые типы всегда должны быть N

Другой вопрос чем его представить внутри кода C#. Т.е. что давать на вход. С целыми понятно: Int32, а вот с дробными вопрос. Выбирал между decimal и double. Второй предпочтительнее оказался, т.к. этот тип процессор понимает, т.е. быстрее работает. Теоретически возможна проблема с точностью, но лично мне она не критична, т.к. double это точность 15 десятичных знаков - больше начинаются погрешности. Мне больше 10 никогда не надо, поэтому не критично если даже в расчетах поучаствуют.

Если надо - могу добавить Set(Int32 col_num, Decimal value). По большому счету одно из двух:
1. в Set(Int32 col_num, Double value) заменить Double на Decimal
2. Привести Decimal к Double и Set(Int32 col_num, Double value)

Надо только потестить как быстрее работать будет. Подозреваю что по варианту 2.

Да можно и double, мне не принципиально для конкретной задачи.
Вот чего не хватает реально, это DateTime?.
Нужно пустую дату записать. Ее чем заменяют в dbf? 8 пробелов?
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123034
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasВот чего не хватает реально, это DateTime?.
Нужно пустую дату записать. Ее чем заменяют в dbf? 8 пробелов?
Да. 8 пробелов.

У себя для записи пустой даты такой вариант предусмотрел
Код: c#
1.
dbf.Set(3, new DateTime());


Или можно вообще не писать, т.к. по умолчанию пробелы.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123037
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TbarrabasВот чего не хватает реально, это DateTime?.
Нужно пустую дату записать. Ее чем заменяют в dbf? 8 пробелов?
Да. 8 пробелов.

У себя для записи пустой даты такой вариант предусмотрел
Код: c#
1.
dbf.Set(3, new DateTime());


Или можно вообще не писать, т.к. по умолчанию пробелы.
А понял, просто пропустить Set, если null.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123040
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TbarrabasВот чего не хватает реально, это DateTime?.
Нужно пустую дату записать. Ее чем заменяют в dbf? 8 пробелов?
Да. 8 пробелов.

У себя для записи пустой даты такой вариант предусмотрел
Код: c#
1.
dbf.Set(3, new DateTime());


Или можно вообще не писать, т.к. по умолчанию пробелы.
не обратил внимание на if (value.Year > 1) :)
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123062
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasА понял, просто пропустить Set, если null.
Да. В DBF можно любые поля вообще не писать, т.е. оставлять пробелы. Тогда загрузчик будет его считать пустым и подставлять для чисел 0, строк "" и т.д., но это не null. null по другому делается.
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123245
Фотография barrabas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

В конце ты не ставишь EOF-маркер = 1A
...
Рейтинг: 0 / 0
Microsoft.Jet.OLEDB.4.0" не зарегистрирован
    #39123267
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
barrabasDima T,

В конце ты не ставишь EOF-маркер = 1A
Не заметил. Похоже его никто не проверяет. В FoxPro открываются, в экселе тоже.

У тебя где-то не прочиталось?

Добавил. Добавь в коде выделенную строчку
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
        public void Close() {
            if (fs == null) return;
            // Конец файла
            fs.WriteByte(0x1A);
            // Заголовок
            fs.Position = 0;
            var buf = new Byte[32];
            buf[0] = 0x03; //  	dBASE III, dBASE IV, dBASE 5, dBASE 7, FoxPro, FoxBASE+
            buf[1] = (Byte)(DateTime.Today.Year - 1900); // Дата последней модификации в виде ГГММДД
            buf[2] = (Byte)(DateTime.Today.Month);
            buf[3] = (Byte)(DateTime.Today.Day);
            buf[4] = (Byte)(row_count & 0xFF); // Число записей в базе 
            buf[5] = (Byte)((row_count >> 8) & 0xFF);
            buf[6] = (Byte)((row_count >> 16) & 0xFF);
            buf[7] = (Byte)((row_count >> 24) & 0xFF);
            Int32 hdr = 32 + 32 * fields.Length + 1; // Полная длина заголовка (с дескрипторами полей)
            buf[8] = (Byte)(hdr & 0xFF);
            buf[9] = (Byte)((hdr >> 8) & 0xFF);
            buf[10] = (Byte)((row_size + 1) & 0xFF); // Длина одной записи
            buf[11] = (Byte)(((row_size + 1) >> 8) & 0xFF);
            buf[29] = (Byte)(encoder.CodePage == 866 ? 0x65 : 0xC9); // Кодовая страница
            fs.Write(buf, 0, 32);
            // Поля
            foreach (var f in fields) {
                for (Int32 i = 0; i < 32; i++) buf[i] = 0;
                System.Text.Encoding.Default.GetBytes(f.name).CopyTo(buf, 0); // Имя поля
                buf[11] = (Byte)f.type; // Тип поля
                buf[16] = (Byte)f.size; // Полная длина поля
                buf[17] = (Byte)f.digs; // Число десятичных разрядов
                fs.Write(buf, 0, 32);
            }
            fs.WriteByte(13);
            fs.Close();
            fs = null;
        }


...
Рейтинг: 0 / 0
25 сообщений из 54, страница 2 из 3
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Microsoft.Jet.OLEDB.4.0" не зарегистрирован
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]