Import dotnetDBF for error handling.
This commit is contained in:
@@ -5,6 +5,10 @@ VisualStudioVersion = 16.0.29613.14
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImEXOnlinePartner", "BodyshopUploader\ImEXOnlinePartner.csproj", "{76B98E9B-A33A-464F-A07B-56E773376543}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImEXOnlinePartner", "BodyshopUploader\ImEXOnlinePartner.csproj", "{76B98E9B-A33A-464F-A07B-56E773376543}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetDBF", "dotnetdbf\DotNetDBF.csproj", "{9508821B-3B85-4088-8076-D0F0AF00DB55}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetDBF.Enumerable", "DotNetDBF.Enumerable\DotNetDBF.Enumerable.csproj", "{83E3893B-E266-475F-BAA4-0BFA8393CDCF}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -27,6 +31,30 @@ Global
|
|||||||
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|Any CPU.Build.0 = Test|Any CPU
|
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|Any CPU.Build.0 = Test|Any CPU
|
||||||
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|x86.ActiveCfg = Test|x86
|
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|x86.ActiveCfg = Test|x86
|
||||||
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|x86.Build.0 = Test|x86
|
{76B98E9B-A33A-464F-A07B-56E773376543}.Test|x86.Build.0 = Test|x86
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Test|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9508821B-3B85-4088-8076-D0F0AF00DB55}.Test|x86.Build.0 = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Test|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{83E3893B-E266-475F-BAA4-0BFA8393CDCF}.Test|x86.Build.0 = Debug|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -348,9 +348,6 @@
|
|||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNetDBF">
|
|
||||||
<Version>6.0.0.3</Version>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="FileHelpers">
|
<PackageReference Include="FileHelpers">
|
||||||
<Version>3.5.1</Version>
|
<Version>3.5.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -537,6 +534,16 @@
|
|||||||
<Version>2.5.1</Version>
|
<Version>2.5.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotNetDBF.Enumerable\DotNetDBF.Enumerable.csproj">
|
||||||
|
<Project>{83e3893b-e266-475f-baa4-0bfa8393cdcf}</Project>
|
||||||
|
<Name>DotNetDBF.Enumerable</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\dotnetdbf\DotNetDBF.csproj">
|
||||||
|
<Project>{9508821b-3b85-4088-8076-d0f0af00db55}</Project>
|
||||||
|
<Name>DotNetDBF</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Release'">
|
<Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Release'">
|
||||||
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
|
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
|
||||||
|
|||||||
@@ -56,4 +56,6 @@ CA63387A44437B55CD283AB4A2CB92385F1321E7 ImEXOnlinePartner-1.0.28-full.nupkg 550
|
|||||||
36869986F57C7F0E25610A10F43C740DAC7639A2 ImEXOnlinePartner-1.0.29-delta.nupkg 56217
|
36869986F57C7F0E25610A10F43C740DAC7639A2 ImEXOnlinePartner-1.0.29-delta.nupkg 56217
|
||||||
6F104EF819C1791FD334CE21CEE9C6B8DB3FC105 ImEXOnlinePartner-1.0.29-full.nupkg 5510931
|
6F104EF819C1791FD334CE21CEE9C6B8DB3FC105 ImEXOnlinePartner-1.0.29-full.nupkg 5510931
|
||||||
D441404BE86E0A676462DD367D4355894C2FFDBA ImEXOnlinePartner-1.0.30-delta.nupkg 62664
|
D441404BE86E0A676462DD367D4355894C2FFDBA ImEXOnlinePartner-1.0.30-delta.nupkg 62664
|
||||||
66963D1624BD0C662CDF6E93B87D9AE4FA8073FF ImEXOnlinePartner-1.0.30-full.nupkg 5512346
|
66963D1624BD0C662CDF6E93B87D9AE4FA8073FF ImEXOnlinePartner-1.0.30-full.nupkg 5512346
|
||||||
|
8F1739F9B7C202F7E2453E7D5027F7422637D206 ImEXOnlinePartner-1.0.31-delta.nupkg 152092
|
||||||
|
6B3D3A0DD81D6F0C302ACE42DEDDDFC11270DD22 ImEXOnlinePartner-1.0.31-full.nupkg 5609086
|
||||||
@@ -1077,8 +1077,8 @@ namespace BodyshopPartner.Utils.Decoder
|
|||||||
|
|
||||||
for (int i = 0; i < reader.RecordCount; i++)
|
for (int i = 0; i < reader.RecordCount; i++)
|
||||||
{
|
{
|
||||||
|
logger.Debug($"Reading line {i +1}");
|
||||||
var readValues = reader.NextRecord();
|
var readValues = reader.NextRecord(false);
|
||||||
dynamic lin = new JObject();
|
dynamic lin = new JObject();
|
||||||
|
|
||||||
//Mising est_seq
|
//Mising est_seq
|
||||||
@@ -1165,7 +1165,12 @@ namespace BodyshopPartner.Utils.Decoder
|
|||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
logger.Trace(ex, "Unable to open LIN file. Retrying. ");
|
logger.Error(ex, "Unable to open LIN file. Retrying. ");
|
||||||
|
retryNumber++;
|
||||||
|
Thread.Sleep(retrySleep);
|
||||||
|
}catch(Exception Ex)
|
||||||
|
{
|
||||||
|
logger.Error(Ex, "Unable to open LIN file. Retrying. Unknown Exception ");
|
||||||
retryNumber++;
|
retryNumber++;
|
||||||
Thread.Sleep(retrySleep);
|
Thread.Sleep(retrySleep);
|
||||||
}
|
}
|
||||||
|
|||||||
504
Copying.TXT
Normal file
504
Copying.TXT
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
||||||
38
DotNetDBF.Enumerable/DotNetDBF.Enumerable.csproj
Normal file
38
DotNetDBF.Enumerable/DotNetDBF.Enumerable.csproj
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net40;netstandard2.0</TargetFrameworks>
|
||||||
|
<SignAssembly>True</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>sn.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<PackageId>dotnetdbf.enumerable</PackageId>
|
||||||
|
<Authors>Jay Tuley</Authors>
|
||||||
|
<Company>Ekon Benefits</Company>
|
||||||
|
<Description>For dotnetdbf projects using .net 4.0 projects this is an enumeration framework in which makes it easy to use Linq to Objects.</Description>
|
||||||
|
<PackageLicense>lgpl</PackageLicense>
|
||||||
|
<PackageProjectUrl>https://github.com/ekonbenefits/dotnetdbf</PackageProjectUrl>
|
||||||
|
<PackageTags>clipper xbase dbf linq</PackageTags>
|
||||||
|
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
|
||||||
|
<PackageIconUrl>https://github.com/ekonbenefits/dotnetdbf</PackageIconUrl>
|
||||||
|
<RepositoryUrl>https://github.com/ekonbenefits/dotnetdbf.git</RepositoryUrl>
|
||||||
|
<RepositoryType>gits</RepositoryType>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<Version>6.0.0.2</Version>
|
||||||
|
<IncludeSymbols>True</IncludeSymbols>
|
||||||
|
<IncludeSource>True</IncludeSource>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\Copying.txt" Pack="true" PackagePath="" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ImpromptuInterface" Version="7.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotNetDBF\DotNetDBF.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
271
DotNetDBF.Enumerable/Enumerable.cs
Normal file
271
DotNetDBF.Enumerable/Enumerable.cs
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using ImpromptuInterface;
|
||||||
|
using Dynamitey;
|
||||||
|
|
||||||
|
namespace DotNetDBF.Enumerable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface to get the contents of the DBF Wrapper
|
||||||
|
/// </summary>
|
||||||
|
public interface IDBFInterceptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Does field exist in row
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool Exists(string fieldName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the data row.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
object[] GetDataRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 618
|
||||||
|
public class DBFInterceptor : DBFIntercepter
|
||||||
|
#pragma warning restore 618
|
||||||
|
{
|
||||||
|
public DBFInterceptor(object[] wrappedObj, string[] fieldNames) : base(wrappedObj, fieldNames)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DBF Dynamic Wrapper
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseDBFInterceptor : Dynamitey.DynamicObjects.BaseObject, IDBFInterceptor
|
||||||
|
{
|
||||||
|
private readonly string[] _fieldNames;
|
||||||
|
private readonly object[] _wrappedArray;
|
||||||
|
|
||||||
|
protected BaseDBFInterceptor(object[] wrappedObj, string[] fieldNames)
|
||||||
|
{
|
||||||
|
_wrappedArray = wrappedObj;
|
||||||
|
_fieldNames = fieldNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> GetDynamicMemberNames()
|
||||||
|
{
|
||||||
|
return _fieldNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Exists(string fieldName)
|
||||||
|
{
|
||||||
|
return _fieldNames.Contains(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
var tLookup = binder.Name;
|
||||||
|
var tIndex = Array.FindIndex(_fieldNames,
|
||||||
|
it => it.Equals(tLookup, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (tIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
result = _wrappedArray[tIndex];
|
||||||
|
|
||||||
|
|
||||||
|
if (TryTypeForName(tLookup, out var outType))
|
||||||
|
{
|
||||||
|
result = Dynamic.CoerceConvert(result, outType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||||
|
{
|
||||||
|
var tLookup = binder.Name;
|
||||||
|
var tIndex = Array.FindIndex(_fieldNames,
|
||||||
|
it => it.Equals(tLookup, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (tIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (TryTypeForName(tLookup, out var outType))
|
||||||
|
{
|
||||||
|
value = Dynamic.CoerceConvert(value, outType);
|
||||||
|
}
|
||||||
|
|
||||||
|
_wrappedArray[tIndex] = value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object[] GetDataRow()
|
||||||
|
{
|
||||||
|
return _wrappedArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerable API
|
||||||
|
/// </summary>
|
||||||
|
public static partial class DBFEnumerable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// New Blank Row Dynamic object that matches writer;
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static dynamic NewBlankRow(this DBFWriter writer)
|
||||||
|
{
|
||||||
|
var fields = writer.Fields.Select(it => it.Name).ToArray();
|
||||||
|
var obj = new object[fields.Length];
|
||||||
|
return new Enumerable.DBFInterceptor(obj, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyRecordTo(this IDBFInterceptor original, IDBFInterceptor dest)
|
||||||
|
{
|
||||||
|
foreach (var fieldName in Dynamitey.Dynamic.GetMemberNames(dest, true))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var val = Dynamic.InvokeGet(original, fieldName);
|
||||||
|
Dynamic.InvokeSet(dest, fieldName, val);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the record.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public static void WriteRecord(this DBFWriter writer, Enumerable.IDBFInterceptor value)
|
||||||
|
{
|
||||||
|
writer.WriteRecord(value.GetDataRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the record.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public static void AddRecord(this DBFWriter writer, Enumerable.IDBFInterceptor value)
|
||||||
|
{
|
||||||
|
writer.AddRecord(value.GetDataRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return all the records. T should be interface with getter properties that match types and names of the database.
|
||||||
|
/// Optionally instead of T being and interface you can pass in an anonymous object with properties that match that
|
||||||
|
/// database and then you'll get an IEnumerable of that anonymous type with the data filled in.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="reader">The reader.</param>
|
||||||
|
/// <param name="prototype">The prototype. Anonymous class instance</param>
|
||||||
|
/// <param name="throwOnParsingError">Indicates if parsing error throws an exception. Default: true</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> AllRecords<T>(this DBFReader reader, T prototype = null, bool throwOnParsingError = true) where T : class
|
||||||
|
{
|
||||||
|
var tType = typeof(T);
|
||||||
|
|
||||||
|
var tProperties = tType.GetProperties()
|
||||||
|
.Where(
|
||||||
|
it =>
|
||||||
|
Array.FindIndex(reader.Fields,
|
||||||
|
f => f.Name.Equals(it.Name, StringComparison.InvariantCultureIgnoreCase)) >= 0)
|
||||||
|
.ToList();
|
||||||
|
var tProps = tProperties
|
||||||
|
.Select(
|
||||||
|
it =>
|
||||||
|
Array.FindIndex(reader.Fields,
|
||||||
|
jt => jt.Name.Equals(it.Name, StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
.Where(it => it >= 0)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var tOrderedProps = tProps.OrderBy(it => it).ToArray();
|
||||||
|
var tReturn = new List<T>();
|
||||||
|
|
||||||
|
|
||||||
|
if (tType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any())
|
||||||
|
{
|
||||||
|
var tAnon = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
|
||||||
|
while (tAnon != null)
|
||||||
|
{
|
||||||
|
tReturn.Add((T) Activator.CreateInstance(tType, tAnon));
|
||||||
|
tAnon = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return tReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
|
||||||
|
|
||||||
|
while (t != null)
|
||||||
|
{
|
||||||
|
var interceptor = new Enumerable.DBFInterceptor(t, tProperties.Select(it => it.Name).ToArray());
|
||||||
|
|
||||||
|
tReturn.Add(interceptor.ActLike<T>(typeof(Enumerable.IDBFInterceptor)));
|
||||||
|
t = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return tReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of dynamic objects whose properties and types match up with that database name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The reader.</param>
|
||||||
|
/// <param name="whereColumn">The where column name.</param>
|
||||||
|
/// <param name="whereColumnEquals">What the were column should equal.</param>
|
||||||
|
/// <param name="throwOnParsingError">Indicates if parsing error throws an exception. Default: true</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<dynamic> DynamicAllRecords(this DBFReader reader, string whereColumn = null,
|
||||||
|
dynamic whereColumnEquals = null, bool throwOnParsingError = true)
|
||||||
|
{
|
||||||
|
var props = reader.GetSelectFields().Select(it => it.Name).ToArray();
|
||||||
|
|
||||||
|
int? whereColumnIndex = null;
|
||||||
|
if (!String.IsNullOrEmpty(whereColumn))
|
||||||
|
{
|
||||||
|
whereColumnIndex = Array.FindIndex(props,
|
||||||
|
it => it.Equals(whereColumn, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var tReturn = new List<object>();
|
||||||
|
var t = reader.NextRecord(throwOnParsingError);
|
||||||
|
|
||||||
|
while (t != null)
|
||||||
|
{
|
||||||
|
if (whereColumnIndex is int i)
|
||||||
|
{
|
||||||
|
dynamic tO = t[i];
|
||||||
|
if (!tO.Equals(whereColumnEquals))
|
||||||
|
{
|
||||||
|
t = reader.NextRecord(throwOnParsingError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var interceptor = new Enumerable.DBFInterceptor(t, props);
|
||||||
|
|
||||||
|
|
||||||
|
tReturn.Add(interceptor);
|
||||||
|
t = reader.NextRecord(throwOnParsingError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return tReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
128
DotNetDBF.Enumerable/Obsolete.cs
Normal file
128
DotNetDBF.Enumerable/Obsolete.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
// ReSharper disable StringLiteralTypo
|
||||||
|
// ReSharper disable IdentifierTypo
|
||||||
|
|
||||||
|
|
||||||
|
namespace DotNetDBF.Enumerable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface to get the contents of the DBF Wrapper
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.IDBFInterceptor is the new interface name",error:true)]
|
||||||
|
public interface IDBFIntercepter:IDBFInterceptor
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.DBFInterceptor is the new class name")]
|
||||||
|
public class DBFIntercepter : DBFEnumerable.DBFIntercepter
|
||||||
|
{
|
||||||
|
public DBFIntercepter(object[] wrappedObj, string[] fieldNames) : base(wrappedObj, fieldNames)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace DotNetDBF.Enumerable
|
||||||
|
{
|
||||||
|
public static partial class DBFEnumerable
|
||||||
|
{
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.IDBFIntercepter is the new interface name")]
|
||||||
|
public interface IDBFIntercepter : DotNetDBF.Enumerable.IDBFIntercepter
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.DBFIntercepter is the new class name")]
|
||||||
|
public class DBFIntercepter : DotNetDBF.Enumerable.Enuemrable.DBFIntercepter, IDBFIntercepter
|
||||||
|
{
|
||||||
|
public DBFIntercepter(object[] wrappedObj, string[] fieldNames)
|
||||||
|
: base(wrappedObj, fieldNames)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Obsolete("DBFEnumerable is the new class name")]
|
||||||
|
public static class Enuemrable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// New Blank Row Dynamic object that matches writer;
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static dynamic NewBlankRow(DBFWriter writer)
|
||||||
|
{
|
||||||
|
return writer.NewBlankRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the record.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public static void WriteRecord(DBFWriter writer, IDBFIntercepter value)
|
||||||
|
{
|
||||||
|
writer.WriteRecord(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the record.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
public static void AddRecord(DBFWriter writer, IDBFIntercepter value)
|
||||||
|
{
|
||||||
|
writer.AddRecord(writer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return all the records. T should be interface with getter properties that match types and names of the database.
|
||||||
|
/// Optionally instead of T being and interface you can pass in an anonymous object with properties that match that
|
||||||
|
/// database and then you'll get an IEnumerable of that anonymous type with the data filled in.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="reader">The reader.</param>
|
||||||
|
/// <param name="prototype">The prototype. Anonymous class instance</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> AllRecords<T>(DBFReader reader, T prototype = null) where T : class
|
||||||
|
{
|
||||||
|
return reader.AllRecords(prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of dynamic objects whose properties and types match up with that database name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The reader.</param>
|
||||||
|
/// <param name="whereColumn">The where column name.</param>
|
||||||
|
/// <param name="whereColumnEquals">What the were column should equal.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<dynamic> DynamicAllRecords(DBFReader reader, string whereColumn = null,
|
||||||
|
dynamic whereColumnEquals = null)
|
||||||
|
{
|
||||||
|
return reader.DynamicAllRecords(whereColumn, (object) whereColumnEquals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.IDBFIntercepter is the new interface name",error:true)]
|
||||||
|
public interface IDBFIntercepter : DotNetDBF.Enumerable.IDBFInterceptor
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("DotNetDBF.Enumerable.DBFIntercepter is the new class name")]
|
||||||
|
public class DBFIntercepter : DotNetDBF.Enumerable.BaseDBFInterceptor, IDBFIntercepter
|
||||||
|
{
|
||||||
|
public DBFIntercepter(object[] wrappedObj, string[] fieldNames)
|
||||||
|
: base(wrappedObj, fieldNames)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
DotNetDBF.Enumerable/sn.snk
Normal file
BIN
DotNetDBF.Enumerable/sn.snk
Normal file
Binary file not shown.
43
DotNetDBF.Test/DotNetDBF.Test.csproj
Normal file
43
DotNetDBF.Test/DotNetDBF.Test.csproj
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;net462</TargetFrameworks>
|
||||||
|
<OutputType Condition="'$(TargetFramework)'!='netcoreapp2.0'">Exe</OutputType>
|
||||||
|
<Copyright>Copyright © 2017</Copyright>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="NUnit" Version="3.7.1" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="3.8.*" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.*" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="dbfs\cp1251.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_03.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_30.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_30.fpt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_31.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83.dbt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_missing_memo.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_missing_memo_record_0.yml" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_record_0.yml" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_record_9.yml" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_8b.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_8b.dbt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_f5.dbf" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_f5.fpt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotNetDBF.Enumerable\DotNetDBF.Enumerable.csproj" />
|
||||||
|
<ProjectReference Include="..\DotNetDBF\DotNetDBF.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="dbfs\cp1251_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_03_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_30_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_31_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_schema.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_83_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_8b_summary.txt" />
|
||||||
|
<EmbeddedResource Include="dbfs\dbase_f5_summary.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
31
DotNetDBF.Test/Issue19Test.cs
Normal file
31
DotNetDBF.Test/Issue19Test.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotNetDBF.Test
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class Issue19Test
|
||||||
|
{
|
||||||
|
private Stream DbfsData(string filename) => typeof(Issue19Test).Assembly
|
||||||
|
.GetManifestResourceStream($"{nameof(DotNetDBF)}.{nameof(Test)}.dbfs.{filename}");
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ReadTest()
|
||||||
|
{
|
||||||
|
using (var dbfstream = DbfsData("dbase_8b.dbf"))
|
||||||
|
using (var memoStream = DbfsData("dbase_8b.dbt"))
|
||||||
|
using (DBFReader dbfr = new DBFReader(dbfstream) { DataMemo = memoStream})
|
||||||
|
{
|
||||||
|
object[] record = dbfr.NextRecord();
|
||||||
|
//This line would hang issue #19 https://github.com/ekonbenefits/dotnetdbf/issues/19
|
||||||
|
Assert.Throws<DBTException>(() => record[5].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
DotNetDBF.Test/Program.cs
Normal file
16
DotNetDBF.Test/Program.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotNetDBF.Test
|
||||||
|
{
|
||||||
|
#if !NETCOREAPP2_0
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
11
DotNetDBF.Test/Properties/AssemblyInfo.cs
Normal file
11
DotNetDBF.Test/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("8d5436e3-f584-40a0-acdc-65346eceadb0")]
|
||||||
544
DotNetDBF.Test/Test.cs
Normal file
544
DotNetDBF.Test/Test.cs
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using DotNetDBF;
|
||||||
|
using DotNetDBF.Enumerable;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotNetDBFTest
|
||||||
|
{
|
||||||
|
public interface ITestInterface
|
||||||
|
{
|
||||||
|
string F1 { get; set; }
|
||||||
|
|
||||||
|
string F2 { get; set; }
|
||||||
|
|
||||||
|
string F3 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class DotNetDBFTest : AssertionHelper
|
||||||
|
{
|
||||||
|
private string TestPath([CallerMemberName] string name = null)
|
||||||
|
=> Path.Combine(Path.GetTempPath(), name + "_121212.dbf");
|
||||||
|
|
||||||
|
private string TestRAFPath([CallerMemberName] string name = null)
|
||||||
|
=> Path.Combine(Path.GetTempPath(), name + "_raf-1212.dbf");
|
||||||
|
|
||||||
|
|
||||||
|
private string TestClipLongPath([CallerMemberName] string name = null)
|
||||||
|
=> Path.Combine(Path.GetTempPath(), name + "_cliplong.dbf");
|
||||||
|
|
||||||
|
private string TestMemoPath([CallerMemberName] string name = null)
|
||||||
|
=> Path.Combine(Path.GetTempPath(), name + "_clipmemo.dbf");
|
||||||
|
|
||||||
|
private string TestSelectPath([CallerMemberName] string name = null)
|
||||||
|
=> Path.Combine(Path.GetTempPath(), name + "_select.dbf");
|
||||||
|
|
||||||
|
private string GetCharacters(int aLength)
|
||||||
|
{
|
||||||
|
var chars = new[] {"a", "b", "c", "d", "e", "f", "g", " "};
|
||||||
|
var returnval = string.Join(string.Empty,
|
||||||
|
Enumerable.Range(0, aLength).Select(it => chars[it % chars.Length]).ToArray());
|
||||||
|
Assert.That(returnval.Length, EqualTo(aLength), "GetCharacters() did not return correct length string");
|
||||||
|
return returnval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void println(String s)
|
||||||
|
{
|
||||||
|
Console.WriteLine(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkDataType_N()
|
||||||
|
{
|
||||||
|
Decimal writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var writer = new DBFWriter())
|
||||||
|
{
|
||||||
|
var field = new DBFField("F1", NativeDbType.Numeric, 15, 0);
|
||||||
|
writer.Fields = new[] {field};
|
||||||
|
|
||||||
|
writtenValue = 123456789012345L;
|
||||||
|
writer.AddRecord(writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestPath(),
|
||||||
|
FileMode.Open,
|
||||||
|
FileAccess.Read))
|
||||||
|
using (var reader = new DBFReader(fis))
|
||||||
|
{
|
||||||
|
var readValues = reader.NextRecord();
|
||||||
|
|
||||||
|
Assert.That(readValues[0], EqualTo(writtenValue), "Written Value Equals Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkLongCharLengthWithClipper()
|
||||||
|
{
|
||||||
|
var fieldLength = 750;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestClipLongPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var writer = new DBFWriter();
|
||||||
|
var field = new DBFField("F1", NativeDbType.Char, fieldLength);
|
||||||
|
writer.Fields = new[] {field};
|
||||||
|
|
||||||
|
writtenValue = GetCharacters(fieldLength);
|
||||||
|
writer.AddRecord(writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestClipLongPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var reader = new DBFReader(fis);
|
||||||
|
Assert.That(reader.Fields.First().FieldLength, EqualTo(fieldLength));
|
||||||
|
var readValues = reader.NextRecord();
|
||||||
|
|
||||||
|
Assert.That(readValues[0], EqualTo(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkDataType_M()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
MemoValue writtenValue;
|
||||||
|
using (Stream fos = File.Open(TestMemoPath(), FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||||
|
using (var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestMemoPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
writer.Fields = new[] {field};
|
||||||
|
|
||||||
|
writtenValue = new MemoValue(GetCharacters(fieldLength));
|
||||||
|
writer.AddRecord(writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (Stream fis = File.Open(TestMemoPath(), FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||||
|
using (var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestMemoPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.NextRecord();
|
||||||
|
|
||||||
|
Assert.That(readValues[0], EqualTo(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkSelect()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
};
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 10, writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
};
|
||||||
|
reader.SetSelectFields("F3");
|
||||||
|
var readValues = reader.NextRecord();
|
||||||
|
|
||||||
|
Assert.That(readValues[0], StartsWith(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkSelectDynamic()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
string writtenMemo;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writtenMemo = GetCharacters(fieldLength);
|
||||||
|
writer.AddRecord(new MemoValue(writtenMemo), 10, writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
reader.SetSelectFields("F1", "F3");
|
||||||
|
var readValues = reader.DynamicAllRecords().First();
|
||||||
|
|
||||||
|
Assert.That(readValues.F1.ToString(), EqualTo(writtenMemo), "Written Value not equaling Read");
|
||||||
|
Assert.That(readValues.F3, EqualTo(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkAnnoymous()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
};
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 10, writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
};
|
||||||
|
|
||||||
|
var readValues = reader.AllRecords(new {F2 = default(decimal), F3 = default(string)});
|
||||||
|
|
||||||
|
Assert.That(readValues.First().F3, StartsWith(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkProxy()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
using (var writer = new DBFWriter {
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
|
||||||
|
;
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 10, writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
using (var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
|
||||||
|
var readValues = reader.AllRecords<ITestInterface>();
|
||||||
|
|
||||||
|
Assert.That(readValues.First().F3, StartsWith(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkDynamicProxy()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 10, writtenValue);
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.DynamicAllRecords();
|
||||||
|
|
||||||
|
Assert.That(readValues.First().F3, StartsWith(writtenValue), "Written Value not equaling Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkDynamicProxyWhere()
|
||||||
|
{
|
||||||
|
var fieldLength = 2400;
|
||||||
|
string writtenValue;
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestSelectPath(),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var writer = new DBFWriter
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var field = new DBFField("F1", NativeDbType.Memo);
|
||||||
|
var field2 = new DBFField("F2", NativeDbType.Numeric, 10);
|
||||||
|
var field3 = new DBFField("F3", NativeDbType.Char, 10);
|
||||||
|
writer.Fields = new[] {field, field2, field3};
|
||||||
|
|
||||||
|
writtenValue = "alpha";
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 10, writtenValue);
|
||||||
|
|
||||||
|
writer.AddRecord(new MemoValue(GetCharacters(fieldLength)), 12, "beta");
|
||||||
|
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var reader = new DBFReader(TestSelectPath())
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.DynamicAllRecords();
|
||||||
|
|
||||||
|
Assert.That(Equals(readValues.Count(), 2), "All Records not matching");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var reader = new DBFReader(TestSelectPath())
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.DynamicAllRecords(whereColumn: "F2", whereColumnEquals: 10);
|
||||||
|
|
||||||
|
Assert.That(Equals(readValues.Count(), 1), "All Records not matching");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var reader = new DBFReader(TestSelectPath())
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.DynamicAllRecords(whereColumn: "F2", whereColumnEquals: 12);
|
||||||
|
|
||||||
|
Assert.That(Equals(readValues.Count(), 1), "All Records not matching");
|
||||||
|
}
|
||||||
|
using (var reader = new DBFReader(TestSelectPath())
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(TestSelectPath(), "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.DynamicAllRecords(whereColumn: "F2", whereColumnEquals: 13);
|
||||||
|
|
||||||
|
Assert.That(Equals(readValues.Count(), 0), "All Records not matching");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void checkRAFwriting()
|
||||||
|
{
|
||||||
|
println("Writing in RAF mode ... ");
|
||||||
|
|
||||||
|
if (File.Exists(TestRAFPath()))
|
||||||
|
{
|
||||||
|
File.Delete(TestRAFPath());
|
||||||
|
}
|
||||||
|
using (var writer = new DBFWriter(TestRAFPath()))
|
||||||
|
{
|
||||||
|
var fields = new DBFField[2];
|
||||||
|
|
||||||
|
fields[0] = new DBFField("F1", NativeDbType.Char, 10);
|
||||||
|
|
||||||
|
fields[1] = new DBFField("F2", NativeDbType.Numeric, 2);
|
||||||
|
|
||||||
|
writer.Fields = fields;
|
||||||
|
|
||||||
|
|
||||||
|
writer.WriteRecord("Red", 10);
|
||||||
|
writer.WriteRecord("Blue", 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
println("done.");
|
||||||
|
|
||||||
|
println("Appending to this file");
|
||||||
|
|
||||||
|
using (var writer = new DBFWriter(TestRAFPath()))
|
||||||
|
{
|
||||||
|
writer.WriteRecord("Green", 33);
|
||||||
|
|
||||||
|
writer.WriteRecord("Yellow", 44);
|
||||||
|
}
|
||||||
|
println("done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShowPaths()
|
||||||
|
{
|
||||||
|
println(TestPath());
|
||||||
|
|
||||||
|
println(TestRAFPath());
|
||||||
|
|
||||||
|
println(TestClipLongPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test()
|
||||||
|
{
|
||||||
|
using (
|
||||||
|
Stream fis =
|
||||||
|
File.Open(@"f:\st\dev\testdata\p.dbf",
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
using (var reader = new DBFReader(fis)
|
||||||
|
{
|
||||||
|
DataMemoLoc = Path.ChangeExtension(@"f:\st\dev\testdata\p.dbf", "DBT")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var readValues = reader.NextRecord();
|
||||||
|
|
||||||
|
Console.WriteLine(readValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void test1()
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrow(() => { new DBFWriter(); }, "Can't Create empty DBFWriter Object");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void test2()
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrow(() => { new DBFField(); }, "Can't Create empty DBFWriter Object");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void test3()
|
||||||
|
{
|
||||||
|
WriteSample();
|
||||||
|
ReadSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteSample([CallerMemberName] string name = null)
|
||||||
|
{
|
||||||
|
var field = new DBFField {Name = "F1", DataType = NativeDbType.Numeric};
|
||||||
|
var writer = new DBFWriter {Fields = new[] {field}};
|
||||||
|
writer.AddRecord(3);
|
||||||
|
using (
|
||||||
|
Stream fos =
|
||||||
|
File.Open(TestPath(name),
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
writer.Write(fos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ReadSample([CallerMemberName] string name = null)
|
||||||
|
{
|
||||||
|
using (var reader = new DBFReader(TestPath(name)))
|
||||||
|
{
|
||||||
|
Assert.That(reader.RecordCount, EqualTo(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
DotNetDBF.Test/dbfs/Readme.md
Normal file
22
DotNetDBF.Test/dbfs/Readme.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Most of the DBFs here are from the spec directory of the dbf ruby gem
|
||||||
|
|
||||||
|
Copyright (c) 2006-2017 Keith Morrison <keithm@infused.org>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
BIN
DotNetDBF.Test/dbfs/cp1251.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/cp1251.dbf
Normal file
Binary file not shown.
11
DotNetDBF.Test/dbfs/cp1251_summary.txt
Normal file
11
DotNetDBF.Test/dbfs/cp1251_summary.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
Database: cp1251.dbf
|
||||||
|
Type: (30) Visual FoxPro
|
||||||
|
Memo File: false
|
||||||
|
Records: 4
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
RN N 4 0
|
||||||
|
NAME C 100 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_03.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_03.dbf
Normal file
Binary file not shown.
40
DotNetDBF.Test/dbfs/dbase_03_summary.txt
Normal file
40
DotNetDBF.Test/dbfs/dbase_03_summary.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
Database: dbase_03.dbf
|
||||||
|
Type: (03) dBase III without memo file
|
||||||
|
Memo File: false
|
||||||
|
Records: 14
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Point_ID C 12 0
|
||||||
|
Type C 20 0
|
||||||
|
Shape C 20 0
|
||||||
|
Circular_D C 20 0
|
||||||
|
Non_circul C 60 0
|
||||||
|
Flow_prese C 20 0
|
||||||
|
Condition C 20 0
|
||||||
|
Comments C 60 0
|
||||||
|
Date_Visit D 8 0
|
||||||
|
Time C 10 0
|
||||||
|
Max_PDOP N 5 1
|
||||||
|
Max_HDOP N 5 1
|
||||||
|
Corr_Type C 36 0
|
||||||
|
Rcvr_Type C 36 0
|
||||||
|
GPS_Date D 8 0
|
||||||
|
GPS_Time C 10 0
|
||||||
|
Update_Sta C 36 0
|
||||||
|
Feat_Name C 20 0
|
||||||
|
Datafile C 20 0
|
||||||
|
Unfilt_Pos N 10 0
|
||||||
|
Filt_Pos N 10 0
|
||||||
|
Data_Dicti C 20 0
|
||||||
|
GPS_Week N 6 0
|
||||||
|
GPS_Second N 12 3
|
||||||
|
GPS_Height N 16 3
|
||||||
|
Vert_Prec N 16 1
|
||||||
|
Horz_Prec N 16 1
|
||||||
|
Std_Dev N 16 6
|
||||||
|
Northing N 16 3
|
||||||
|
Easting N 16 3
|
||||||
|
Point_ID N 9 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_30.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_30.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/dbase_30.fpt
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_30.fpt
Normal file
Binary file not shown.
154
DotNetDBF.Test/dbfs/dbase_30_summary.txt
Normal file
154
DotNetDBF.Test/dbfs/dbase_30_summary.txt
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
Database: dbase_30.dbf
|
||||||
|
Type: (30) Visual FoxPro
|
||||||
|
Memo File: true
|
||||||
|
Records: 34
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ACCESSNO C 15 0
|
||||||
|
ACQVALUE N 12 2
|
||||||
|
APPNOTES M 4 0
|
||||||
|
APPRAISOR C 75 0
|
||||||
|
CABINET C 25 0
|
||||||
|
CAPTION C 30 0
|
||||||
|
CAT C 1 0
|
||||||
|
CATBY C 25 0
|
||||||
|
CATDATE D 8 0
|
||||||
|
CATTYPE C 15 0
|
||||||
|
CLASSES M 4 0
|
||||||
|
COLLECTION C 75 0
|
||||||
|
CONDDATE D 8 0
|
||||||
|
CONDEXAM C 25 0
|
||||||
|
CONDITION C 35 0
|
||||||
|
CONDNOTES M 4 0
|
||||||
|
CONTAINER C 40 0
|
||||||
|
COPYRIGHT M 4 0
|
||||||
|
CREATOR C 80 0
|
||||||
|
CREDIT M 4 0
|
||||||
|
CURVALMAX N 12 2
|
||||||
|
CURVALUE N 12 2
|
||||||
|
DATASET C 15 0
|
||||||
|
DATE C 50 0
|
||||||
|
DESCRIP M 4 0
|
||||||
|
DIMNOTES M 4 0
|
||||||
|
DISPVALUE C 10 0
|
||||||
|
DRAWER C 20 0
|
||||||
|
EARLYDATE N 4 0
|
||||||
|
EVENT C 80 0
|
||||||
|
EXHIBITID C 36 0
|
||||||
|
EXHIBITNO N 7 0
|
||||||
|
EXHLABEL1 M 4 0
|
||||||
|
EXHLABEL2 M 4 0
|
||||||
|
EXHLABEL3 M 4 0
|
||||||
|
EXHLABEL4 M 4 0
|
||||||
|
EXHSTART D 8 0
|
||||||
|
FILMSIZE C 35 0
|
||||||
|
FLAGDATE T 8 0
|
||||||
|
FLAGNOTES M 4 0
|
||||||
|
FLAGREASON C 20 0
|
||||||
|
FRAME C 75 0
|
||||||
|
FRAMENO C 25 0
|
||||||
|
GPARENT C 45 0
|
||||||
|
HOMELOC C 60 0
|
||||||
|
IMAGEFILE C 60 0
|
||||||
|
IMAGENO N 3 0
|
||||||
|
INSCOMP C 30 0
|
||||||
|
INSDATE D 8 0
|
||||||
|
INSPHONE C 25 0
|
||||||
|
INSPREMIUM C 20 0
|
||||||
|
INSREP C 30 0
|
||||||
|
INSVALUE N 10 2
|
||||||
|
INVNBY C 25 0
|
||||||
|
INVNDATE D 8 0
|
||||||
|
LATEDATE N 4 0
|
||||||
|
LEGAL M 4 0
|
||||||
|
LOANCOND M 4 0
|
||||||
|
LOANDATE D 8 0
|
||||||
|
LOANDUE D 8 0
|
||||||
|
LOANID C 36 0
|
||||||
|
LOANINNO C 15 0
|
||||||
|
MAINTCYCLE C 10 0
|
||||||
|
MAINTDATE D 8 0
|
||||||
|
MAINTNOTE M 4 0
|
||||||
|
MEDIUM C 75 0
|
||||||
|
NEGLOC C 60 0
|
||||||
|
NEGNO C 25 0
|
||||||
|
NOTES M 4 0
|
||||||
|
OBJECTID C 25 0
|
||||||
|
OBJNAME C 40 0
|
||||||
|
OLDNO C 25 0
|
||||||
|
ORIGCOPY C 15 0
|
||||||
|
OTHERNO C 25 0
|
||||||
|
OUTDATE D 8 0
|
||||||
|
PARENT C 40 0
|
||||||
|
PEOPLE M 4 0
|
||||||
|
PLACE C 100 0
|
||||||
|
POLICYNO C 20 0
|
||||||
|
PRINTSIZE C 35 0
|
||||||
|
PROCESS C 75 0
|
||||||
|
PROVENANCE M 4 0
|
||||||
|
PUBNOTES M 4 0
|
||||||
|
RECAS C 20 0
|
||||||
|
RECDATE C 10 0
|
||||||
|
RECFROM C 120 0
|
||||||
|
RELATION C 36 0
|
||||||
|
RELNOTES M 4 0
|
||||||
|
ROOM C 25 0
|
||||||
|
SGFLAG C 1 0
|
||||||
|
SHELF C 20 0
|
||||||
|
SITE C 40 0
|
||||||
|
SITENO C 12 0
|
||||||
|
SLIDENO C 25 0
|
||||||
|
STATUS C 20 0
|
||||||
|
STATUSBY C 25 0
|
||||||
|
STATUSDATE D 8 0
|
||||||
|
STERMS M 4 0
|
||||||
|
STUDIO C 60 0
|
||||||
|
SUBJECTS M 4 0
|
||||||
|
TCABINET C 25 0
|
||||||
|
TCONTAINER C 40 0
|
||||||
|
TDRAWER C 20 0
|
||||||
|
TEMPAUTHOR C 25 0
|
||||||
|
TEMPBY C 25 0
|
||||||
|
TEMPDATE D 8 0
|
||||||
|
TEMPLOC C 60 0
|
||||||
|
TEMPNOTES M 4 0
|
||||||
|
TEMPREASON C 50 0
|
||||||
|
TEMPUNTIL C 10 0
|
||||||
|
TITLE M 4 0
|
||||||
|
TITLESORT C 100 0
|
||||||
|
TROOM C 25 0
|
||||||
|
TSHELF C 20 0
|
||||||
|
TWALL C 20 0
|
||||||
|
UDF1 C 75 0
|
||||||
|
UDF10 C 75 0
|
||||||
|
UDF11 C 20 0
|
||||||
|
UDF12 C 20 0
|
||||||
|
UDF13 N 12 0
|
||||||
|
UDF14 N 12 2
|
||||||
|
UDF15 N 12 2
|
||||||
|
UDF16 N 12 3
|
||||||
|
UDF17 N 12 3
|
||||||
|
UDF18 D 8 0
|
||||||
|
UDF19 D 8 0
|
||||||
|
UDF20 D 8 0
|
||||||
|
UDF21 M 4 0
|
||||||
|
UDF22 M 4 0
|
||||||
|
UDF2 C 75 0
|
||||||
|
UDF3 C 75 0
|
||||||
|
UDF4 C 75 0
|
||||||
|
UDF5 C 75 0
|
||||||
|
UDF6 C 75 0
|
||||||
|
UDF7 C 75 0
|
||||||
|
UDF8 C 75 0
|
||||||
|
UDF9 C 75 0
|
||||||
|
UPDATED T 8 0
|
||||||
|
UPDATEDBY C 25 0
|
||||||
|
VALUEDATE D 8 0
|
||||||
|
WALL C 20 0
|
||||||
|
WEBINCLUDE L 1 0
|
||||||
|
ZSORTER C 69 0
|
||||||
|
ZSORTERX C 44 0
|
||||||
|
PPID C 36 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_31.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_31.dbf
Normal file
Binary file not shown.
20
DotNetDBF.Test/dbfs/dbase_31_summary.txt
Normal file
20
DotNetDBF.Test/dbfs/dbase_31_summary.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Database: dbase_31.dbf
|
||||||
|
Type: (31) Visual FoxPro with AutoIncrement field
|
||||||
|
Memo File: false
|
||||||
|
Records: 77
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
PRODUCTID I 4 0
|
||||||
|
PRODUCTNAM C 40 0
|
||||||
|
SUPPLIERID I 4 0
|
||||||
|
CATEGORYID I 4 0
|
||||||
|
QUANTITYPE C 20 0
|
||||||
|
UNITPRICE Y 8 4
|
||||||
|
UNITSINSTO I 4 0
|
||||||
|
UNITSONORD I 4 0
|
||||||
|
REORDERLEV I 4 0
|
||||||
|
DISCONTINU L 1 0
|
||||||
|
_NullFlags 0 1 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_83.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_83.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/dbase_83.dbt
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_83.dbt
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/dbase_83_missing_memo.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_83_missing_memo.dbf
Normal file
Binary file not shown.
16
DotNetDBF.Test/dbfs/dbase_83_missing_memo_record_0.yml
Normal file
16
DotNetDBF.Test/dbfs/dbase_83_missing_memo_record_0.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
- 87
|
||||||
|
- 2
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 87
|
||||||
|
- '1'
|
||||||
|
- Assorted Petits Fours
|
||||||
|
- graphics/00000001/t_1.jpg
|
||||||
|
- graphics/00000001/1.jpg
|
||||||
|
- 0.0
|
||||||
|
- 0.0
|
||||||
|
-
|
||||||
|
- 5.51
|
||||||
|
- true
|
||||||
|
- true
|
||||||
16
DotNetDBF.Test/dbfs/dbase_83_record_0.yml
Normal file
16
DotNetDBF.Test/dbfs/dbase_83_record_0.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
- 87
|
||||||
|
- 2
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 87
|
||||||
|
- '1'
|
||||||
|
- Assorted Petits Fours
|
||||||
|
- graphics/00000001/t_1.jpg
|
||||||
|
- graphics/00000001/1.jpg
|
||||||
|
- 0.0
|
||||||
|
- 0.0
|
||||||
|
- "Our Original assortment...a little taste of heaven for everyone. Let us\r\nselect a special assortment of our chocolate and pastel favorites for you.\r\nEach petit four is its own special hand decorated creation. Multi-layers of\r\nmoist cake with combinations of specialty fillings create memorable cake\r\nconfections. Varietes include; Luscious Lemon, Strawberry Hearts, White\r\nChocolate, Mocha Bean, Roasted Almond, Triple Chocolate, Chocolate Hazelnut,\r\nGrand Orange, Plum Squares, Milk chocolate squares, and Raspberry Blanc."
|
||||||
|
- 5.51
|
||||||
|
- true
|
||||||
|
- true
|
||||||
23
DotNetDBF.Test/dbfs/dbase_83_record_9.yml
Normal file
23
DotNetDBF.Test/dbfs/dbase_83_record_9.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
- 34
|
||||||
|
- 1
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
- 34
|
||||||
|
- AB01
|
||||||
|
- Apricot Brandy Fruitcake
|
||||||
|
- graphics/00000001/t_AB01.jpg
|
||||||
|
- graphics/00000001/AB01.jpg
|
||||||
|
- 37.95
|
||||||
|
- 37.95
|
||||||
|
- "Once tasted you will understand why we won The\r\nBoston Herald's Fruitcake Taste-off.
|
||||||
|
Judges liked its generous size,\r\nluscious appearance, moist texture and fruit
|
||||||
|
to cake ratio ... commented one\r\njudge \"It's a lip Smacker!\" Our signature fruitcake
|
||||||
|
is baked with carefully\r\nselected ingredients that will be savored until the last
|
||||||
|
moist crumb is\r\ndevoured each golden slice is brimming with Australian glaced
|
||||||
|
apricots,\r\ntoasted pecans, candied orange peel, and currants, folded gently into
|
||||||
|
a\r\nbrandy butter batter and slowly baked to perfection and then generously\r\nimbibed
|
||||||
|
with \"Holiday Spirits\". Presented in a gift tin. (3lbs. 4oz)"
|
||||||
|
- 0.0
|
||||||
|
- false
|
||||||
|
- true
|
||||||
19
DotNetDBF.Test/dbfs/dbase_83_schema.txt
Normal file
19
DotNetDBF.Test/dbfs/dbase_83_schema.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
ActiveRecord::Schema.define do
|
||||||
|
create_table "dbase_83" do |t|
|
||||||
|
t.column "id", :integer
|
||||||
|
t.column "catcount", :integer
|
||||||
|
t.column "agrpcount", :integer
|
||||||
|
t.column "pgrpcount", :integer
|
||||||
|
t.column "order", :integer
|
||||||
|
t.column "code", :string, :limit => 50
|
||||||
|
t.column "name", :string, :limit => 100
|
||||||
|
t.column "thumbnail", :string, :limit => 254
|
||||||
|
t.column "image", :string, :limit => 254
|
||||||
|
t.column "price", :float
|
||||||
|
t.column "cost", :float
|
||||||
|
t.column "desc", :text
|
||||||
|
t.column "weight", :float
|
||||||
|
t.column "taxable", :boolean
|
||||||
|
t.column "active", :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
24
DotNetDBF.Test/dbfs/dbase_83_summary.txt
Normal file
24
DotNetDBF.Test/dbfs/dbase_83_summary.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
Database: dbase_83.dbf
|
||||||
|
Type: (83) dBase III with memo file
|
||||||
|
Memo File: true
|
||||||
|
Records: 67
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ID N 19 0
|
||||||
|
CATCOUNT N 19 0
|
||||||
|
AGRPCOUNT N 19 0
|
||||||
|
PGRPCOUNT N 19 0
|
||||||
|
ORDER N 19 0
|
||||||
|
CODE C 50 0
|
||||||
|
NAME C 100 0
|
||||||
|
THUMBNAIL C 254 0
|
||||||
|
IMAGE C 254 0
|
||||||
|
PRICE N 13 2
|
||||||
|
COST N 13 2
|
||||||
|
DESC M 10 0
|
||||||
|
WEIGHT N 13 2
|
||||||
|
TAXABLE L 1 0
|
||||||
|
ACTIVE L 1 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_8b.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_8b.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/dbase_8b.dbt
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_8b.dbt
Normal file
Binary file not shown.
15
DotNetDBF.Test/dbfs/dbase_8b_summary.txt
Normal file
15
DotNetDBF.Test/dbfs/dbase_8b_summary.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
Database: dbase_8b.dbf
|
||||||
|
Type: (8b) dBase IV with memo file
|
||||||
|
Memo File: true
|
||||||
|
Records: 10
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
CHARACTER C 100 0
|
||||||
|
NUMERICAL N 20 2
|
||||||
|
DATE D 8 0
|
||||||
|
LOGICAL L 1 0
|
||||||
|
FLOAT F 20 18
|
||||||
|
MEMO M 10 0
|
||||||
BIN
DotNetDBF.Test/dbfs/dbase_f5.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_f5.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/dbase_f5.fpt
Normal file
BIN
DotNetDBF.Test/dbfs/dbase_f5.fpt
Normal file
Binary file not shown.
68
DotNetDBF.Test/dbfs/dbase_f5_summary.txt
Normal file
68
DotNetDBF.Test/dbfs/dbase_f5_summary.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
Database: dbase_f5.dbf
|
||||||
|
Type: (f5) FoxPro with memo file
|
||||||
|
Memo File: true
|
||||||
|
Records: 975
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
Name Type Length Decimal
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
NF N 5 0
|
||||||
|
SEXE C 1 0
|
||||||
|
NOM C 20 0
|
||||||
|
COG1 C 15 0
|
||||||
|
COG2 C 15 0
|
||||||
|
TELEFON C 9 0
|
||||||
|
RENOM C 15 0
|
||||||
|
NFP N 5 0
|
||||||
|
NFM N 5 0
|
||||||
|
ARXN C 10 0
|
||||||
|
DATN D 8 0
|
||||||
|
LLON C 15 0
|
||||||
|
MUNN C 15 0
|
||||||
|
COMN C 15 0
|
||||||
|
PROV C 15 0
|
||||||
|
PAIN C 15 0
|
||||||
|
OFIC C 15 0
|
||||||
|
ARXB C 10 0
|
||||||
|
DATB D 8 0
|
||||||
|
LLOB C 15 0
|
||||||
|
MUNB C 15 0
|
||||||
|
COMB C 15 0
|
||||||
|
PAIB C 15 0
|
||||||
|
DRIB C 30 0
|
||||||
|
INAB C 30 0
|
||||||
|
OFTB C 10 0
|
||||||
|
OFNB C 20 0
|
||||||
|
AXC1 C 10 0
|
||||||
|
DTC1 D 8 0
|
||||||
|
LLC1 C 15 0
|
||||||
|
NFC1 N 5 0
|
||||||
|
TCA1 C 10 0
|
||||||
|
OTC1 C 10 0
|
||||||
|
ONC1 C 20 0
|
||||||
|
AXC2 C 10 0
|
||||||
|
DTC2 D 8 0
|
||||||
|
LLC2 C 15 0
|
||||||
|
NFC2 N 5 0
|
||||||
|
TCA2 C 10 0
|
||||||
|
OTC2 C 10 0
|
||||||
|
ONC2 C 20 0
|
||||||
|
AXC3 C 10 0
|
||||||
|
DTC3 D 8 0
|
||||||
|
LLC3 C 15 0
|
||||||
|
NFC3 N 5 0
|
||||||
|
TCA3 C 10 0
|
||||||
|
OTC3 C 10 0
|
||||||
|
ONC3 C 20 0
|
||||||
|
ARXD C 10 0
|
||||||
|
DATD D 8 0
|
||||||
|
LLOD C 15 0
|
||||||
|
OFTD C 10 0
|
||||||
|
OFND C 20 0
|
||||||
|
OBS1 C 70 0
|
||||||
|
OBS2 C 70 0
|
||||||
|
OBS3 C 70 0
|
||||||
|
OBS4 C 70 0
|
||||||
|
OBSE M 10 0
|
||||||
|
GHD C 15 0
|
||||||
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DBC
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DBC
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DCT
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DCT
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DCX
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/FOXPRO-DB-TEST.DCX
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.CDX
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.CDX
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.FPT
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.FPT
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/calls.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.CDX
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.CDX
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.FPT
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.FPT
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/contacts.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/setup.CDX
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/setup.CDX
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/setup.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/setup.dbf
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/types.CDX
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/types.CDX
Normal file
Binary file not shown.
BIN
DotNetDBF.Test/dbfs/foxprodb/types.dbf
Normal file
BIN
DotNetDBF.Test/dbfs/foxprodb/types.dbf
Normal file
Binary file not shown.
9
dotnetdbf/.gitignore
vendored
Normal file
9
dotnetdbf/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
bin
|
||||||
|
obj
|
||||||
|
/packages
|
||||||
|
|
||||||
|
*.suo
|
||||||
|
|
||||||
|
*.user
|
||||||
|
.idea/*
|
||||||
|
.vs/*
|
||||||
44
dotnetdbf/DBFBase.cs
Normal file
44
dotnetdbf/DBFBase.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Serves as the base class of DBFReader adn DBFWriter.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
Support for choosing implemented character Sets as
|
||||||
|
suggested by Nick Voznesensky <darkers@mail.ru>
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
Base class for DBFReader and DBFWriter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public abstract class DBFBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public Encoding CharEncoding { get; set; } = Encoding.GetEncoding("utf-8");
|
||||||
|
|
||||||
|
public int BlockSize { get; set; } = 512;
|
||||||
|
|
||||||
|
private string _nullSymbol;
|
||||||
|
public string NullSymbol
|
||||||
|
{
|
||||||
|
get => _nullSymbol ?? DBFFieldType.Unknown;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != null && value.Length != 1)
|
||||||
|
throw new ArgumentException(nameof(NullSymbol));
|
||||||
|
_nullSymbol = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
62
dotnetdbf/DBFException.cs
Normal file
62
dotnetdbf/DBFException.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
DBFException
|
||||||
|
Represents exceptions happen in the JAvaDBF classes.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public class DBTException : DBFException
|
||||||
|
{
|
||||||
|
|
||||||
|
public DBTException(string msg) : base(msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBTException(string msg, Exception internalException)
|
||||||
|
: base(msg, internalException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DBFRecordException : DBFException
|
||||||
|
{
|
||||||
|
public int Record { get; }
|
||||||
|
|
||||||
|
public DBFRecordException(string msg, int record) : base(msg)
|
||||||
|
{
|
||||||
|
Record = record;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFRecordException(string msg, Exception internalException)
|
||||||
|
: base(msg, internalException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DBFException : IOException
|
||||||
|
{
|
||||||
|
public DBFException() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFException(string msg) : base(msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFException(string msg, Exception internalException)
|
||||||
|
: base(msg, internalException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
309
dotnetdbf/DBFField.cs
Normal file
309
dotnetdbf/DBFField.cs
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
/*
|
||||||
|
DBFField
|
||||||
|
Class represents a "field" (or column) definition of a DBF data structure.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("Field:{Name}, Length:{FieldLength}")]
|
||||||
|
public class DBFField
|
||||||
|
{
|
||||||
|
public const int SIZE = 32;
|
||||||
|
public byte dataType; /* 11 */
|
||||||
|
public byte decimalCount; /* 17 */
|
||||||
|
public int fieldLength; /* 16 */
|
||||||
|
public byte[] fieldName = new byte[11]; /* 0-10*/
|
||||||
|
public byte indexFieldFlag; /* 31 */
|
||||||
|
|
||||||
|
/* other class variables */
|
||||||
|
public int nameNullIndex = 0;
|
||||||
|
public int reserv1; /* 12-15 */
|
||||||
|
public short reserv2; /* 18-19 */
|
||||||
|
public short reserv3; /* 21-22 */
|
||||||
|
public byte[] reserv4 = new byte[7]; /* 24-30 */
|
||||||
|
public byte setFieldsFlag; /* 23 */
|
||||||
|
public byte workAreaId; /* 20 */
|
||||||
|
|
||||||
|
public DBFField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFField(string fieldName, NativeDbType type)
|
||||||
|
{
|
||||||
|
Name = fieldName;
|
||||||
|
DataType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFField(string fieldName,
|
||||||
|
NativeDbType type,
|
||||||
|
int fieldLength)
|
||||||
|
{
|
||||||
|
Name = fieldName;
|
||||||
|
DataType = type;
|
||||||
|
FieldLength = fieldLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFField(string fieldName,
|
||||||
|
NativeDbType type,
|
||||||
|
int fieldLength,
|
||||||
|
int decimalCount)
|
||||||
|
{
|
||||||
|
Name = fieldName;
|
||||||
|
DataType = type;
|
||||||
|
FieldLength = fieldLength;
|
||||||
|
DecimalCount = decimalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Size => SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the name of the field.
|
||||||
|
|
||||||
|
@return Name of the field as String.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => Encoding.ASCII.GetString(fieldName, 0, nameNullIndex);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Field name cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Length == 0
|
||||||
|
|| value.Length > 10)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
"Field name should be of length 0-10");
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName = Encoding.ASCII.GetBytes(value);
|
||||||
|
nameNullIndex = fieldName.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the data type of the field.
|
||||||
|
|
||||||
|
@return Data type as byte.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Type Type => Utils.TypeForNativeDBType(DataType);
|
||||||
|
|
||||||
|
|
||||||
|
public NativeDbType DataType
|
||||||
|
{
|
||||||
|
get => (NativeDbType)dataType;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case NativeDbType.Date:
|
||||||
|
fieldLength = 8; /* fall through */
|
||||||
|
goto default;
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
fieldLength = 10;
|
||||||
|
goto default;
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
fieldLength = 1;
|
||||||
|
goto default;
|
||||||
|
default:
|
||||||
|
dataType = (byte)value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns field length.
|
||||||
|
|
||||||
|
@return field length as int.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public int FieldLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (DataType == NativeDbType.Char)
|
||||||
|
{
|
||||||
|
return fieldLength + (decimalCount * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldLength;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Length of the field.
|
||||||
|
This method should be called before calling setDecimalCount().
|
||||||
|
|
||||||
|
@param Length of the field as int.
|
||||||
|
*/
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
"Field length should be a positive number");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (DataType)
|
||||||
|
{
|
||||||
|
case NativeDbType.Date:
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
throw new NotSupportedException(
|
||||||
|
"Cannot set length on this type of field");
|
||||||
|
case NativeDbType.Char when value > 255:
|
||||||
|
fieldLength = value % 256;
|
||||||
|
decimalCount = (byte) (value / 256);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
fieldLength = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the decimal part. This is applicable
|
||||||
|
only if the field type if of numeric in nature.
|
||||||
|
|
||||||
|
If the field is specified to hold integral values
|
||||||
|
the value returned by this method will be zero.
|
||||||
|
|
||||||
|
@return decimal field size as int.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public int DecimalCount
|
||||||
|
{
|
||||||
|
get => decimalCount;
|
||||||
|
/**
|
||||||
|
Sets the decimal place size of the field.
|
||||||
|
Before calling this method the size of the field
|
||||||
|
should be set by calling setFieldLength().
|
||||||
|
|
||||||
|
@param Size of the decimal field.
|
||||||
|
*/
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
"Decimal length should be a positive number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > fieldLength)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
"Decimal length should be less than field length");
|
||||||
|
}
|
||||||
|
|
||||||
|
decimalCount = (byte) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Read(BinaryReader reader)
|
||||||
|
{
|
||||||
|
var t_byte = reader.ReadByte(); /* 0 */
|
||||||
|
if (t_byte == DBFFieldType.EndOfField)
|
||||||
|
{
|
||||||
|
//System.out.println( "End of header found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Read(fieldName, 1, 10); /* 1-10 */
|
||||||
|
fieldName[0] = t_byte;
|
||||||
|
|
||||||
|
for (var i = 0; i < fieldName.Length; i++)
|
||||||
|
{
|
||||||
|
if (fieldName[i]
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
nameNullIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataType = reader.ReadByte(); /* 11 */
|
||||||
|
reserv1 = reader.ReadInt32(); /* 12-15 */
|
||||||
|
fieldLength = reader.ReadByte(); /* 16 */
|
||||||
|
decimalCount = reader.ReadByte(); /* 17 */
|
||||||
|
reserv2 = reader.ReadInt16(); /* 18-19 */
|
||||||
|
workAreaId = reader.ReadByte(); /* 20 */
|
||||||
|
reserv3 = reader.ReadInt16(); /* 21-22 */
|
||||||
|
setFieldsFlag = reader.ReadByte(); /* 23 */
|
||||||
|
reader.Read(reserv4, 0, 7); /* 24-30 */
|
||||||
|
indexFieldFlag = reader.ReadByte(); /* 31 */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes the content of DBFField object into the stream as per
|
||||||
|
DBF format specifications.
|
||||||
|
|
||||||
|
@param os OutputStream
|
||||||
|
@throws IOException if any stream related issues occur.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
// Field Name
|
||||||
|
writer.Write(fieldName); /* 0-10 */
|
||||||
|
writer.Write(new byte[11 - fieldName.Length],
|
||||||
|
0,
|
||||||
|
11 - fieldName.Length);
|
||||||
|
|
||||||
|
// data type
|
||||||
|
writer.Write(dataType); /* 11 */
|
||||||
|
writer.Write(reserv1); /* 12-15 */
|
||||||
|
writer.Write((byte) fieldLength); /* 16 */
|
||||||
|
writer.Write(decimalCount); /* 17 */
|
||||||
|
writer.Write(reserv2); /* 18-19 */
|
||||||
|
writer.Write(workAreaId); /* 20 */
|
||||||
|
writer.Write(reserv3); /* 21-22 */
|
||||||
|
writer.Write(setFieldsFlag); /* 23 */
|
||||||
|
writer.Write(reserv4); /* 24-30*/
|
||||||
|
writer.Write(indexFieldFlag); /* 31 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a DBFField object from the data read from the given DataInputStream.
|
||||||
|
|
||||||
|
The data in the DataInputStream object is supposed to be organised correctly
|
||||||
|
and the stream "pointer" is supposed to be positioned properly.
|
||||||
|
|
||||||
|
@param in DataInputStream
|
||||||
|
@return Returns the created DBFField object.
|
||||||
|
@throws IOException If any stream reading problems occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
internal static DBFField CreateField(BinaryReader reader)
|
||||||
|
{
|
||||||
|
var field = new DBFField();
|
||||||
|
if (field.Read(reader))
|
||||||
|
{
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
dotnetdbf/DBFFieldType.cs
Normal file
86
dotnetdbf/DBFFieldType.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
DBFFieldType
|
||||||
|
Class for reading the records assuming that the given
|
||||||
|
InputStream comtains DBF data.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
author (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public enum NativeDbType : byte
|
||||||
|
{
|
||||||
|
Autoincrement = (byte) 0x2B, //+ in ASCII
|
||||||
|
Timestamp = (byte) 0x40, //@ in ASCII
|
||||||
|
Binary = (byte) 0x42, //B in ASCII
|
||||||
|
Char = (byte) 0x43, //C in ASCII
|
||||||
|
Date = (byte) 0x44, //D in ASCII
|
||||||
|
Float = (byte) 0x46, //F in ASCII
|
||||||
|
Ole = (byte) 0x47, //G in ASCII
|
||||||
|
Long = (byte) 0x49, //I in ASCII
|
||||||
|
Logical = (byte) 0x4C, //L in ASCII
|
||||||
|
Memo = (byte) 0x4D, //M in ASCII
|
||||||
|
Numeric = (byte) 0x4E, //N in ASCII
|
||||||
|
Double = (byte) 0x4F, //O in ASCII
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DBFFieldType
|
||||||
|
{
|
||||||
|
public const byte EndOfData = 0x1A; //^Z End of File
|
||||||
|
public const byte EndOfField = 0x0D; //End of Field
|
||||||
|
public const byte False = 0x46; //F in Ascii
|
||||||
|
public const byte Space = 0x20; //Space in ascii
|
||||||
|
public const byte True = 0x54; //T in ascii
|
||||||
|
public const byte UnknownByte = 0x3F; //Unknown Bool value
|
||||||
|
public const string Unknown = "?"; //Unknown value
|
||||||
|
|
||||||
|
public static DbType FromNative(NativeDbType @byte)
|
||||||
|
{
|
||||||
|
switch (@byte)
|
||||||
|
{
|
||||||
|
case NativeDbType.Char:
|
||||||
|
return DbType.AnsiStringFixedLength;
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
return DbType.Boolean;
|
||||||
|
case NativeDbType.Numeric:
|
||||||
|
return DbType.Decimal;
|
||||||
|
case NativeDbType.Date:
|
||||||
|
return DbType.Date;
|
||||||
|
case NativeDbType.Float:
|
||||||
|
return DbType.Decimal;
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
return DbType.AnsiString;
|
||||||
|
default:
|
||||||
|
return DbType.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NativeDbType FromDbType(DbType dbType)
|
||||||
|
{
|
||||||
|
switch (dbType)
|
||||||
|
{
|
||||||
|
case DbType.AnsiStringFixedLength:
|
||||||
|
return NativeDbType.Char;
|
||||||
|
case DbType.Boolean:
|
||||||
|
return NativeDbType.Logical;
|
||||||
|
case DbType.Decimal:
|
||||||
|
return NativeDbType.Numeric;
|
||||||
|
case DbType.Date:
|
||||||
|
return NativeDbType.Date;
|
||||||
|
case DbType.AnsiString:
|
||||||
|
return NativeDbType.Memo;
|
||||||
|
default:
|
||||||
|
throw new DBFException(
|
||||||
|
$"Unsupported Type {dbType}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
182
dotnetdbf/DBFHeader.cs
Normal file
182
dotnetdbf/DBFHeader.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
DBFHeader
|
||||||
|
Class for reading the metadata assuming that the given
|
||||||
|
InputStream carries DBF data.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
|
||||||
|
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
[Obsolete("Use DBFSignature instead", error:true)]
|
||||||
|
public static class DBFSigniture
|
||||||
|
{
|
||||||
|
public const byte NotSet = 0,
|
||||||
|
WithMemo = 0x80,
|
||||||
|
DBase3 = 0x03,
|
||||||
|
DBase3WithMemo = DBase3 | WithMemo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DBFSignature
|
||||||
|
{
|
||||||
|
public const byte NotSet = 0,
|
||||||
|
WithMemo = 0x80,
|
||||||
|
DBase3 = 0x03,
|
||||||
|
DBase3WithMemo = DBase3 | WithMemo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum MemoFlags : byte
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DBFHeader
|
||||||
|
{
|
||||||
|
public const byte HeaderRecordTerminator = 0x0D;
|
||||||
|
|
||||||
|
internal byte Signature { get; set; } /* 0 */
|
||||||
|
internal byte Year { set; get; } /* 1 */
|
||||||
|
internal byte Month { set; get; } /* 2 */
|
||||||
|
internal byte Day { set; get; } /* 3 */
|
||||||
|
internal int NumberOfRecords { set; get; } /* 4-7 */
|
||||||
|
internal short HeaderLength { set; get; } /* 8-9 */
|
||||||
|
internal short RecordLength { set; get; } /* 10-11 */
|
||||||
|
private short _reserv1; /* 12-13 */
|
||||||
|
private byte _incompleteTransaction; /* 14 */
|
||||||
|
private byte _encryptionFlag; /* 15 */
|
||||||
|
private int _freeRecordThread; /* 16-19 */
|
||||||
|
private int _reserv2; /* 20-23 */
|
||||||
|
private int _reserv3; /* 24-27 */
|
||||||
|
private byte _mdxFlag; /* 28 */
|
||||||
|
internal byte LanguageDriver { get; set; } /* 29 */
|
||||||
|
private short _reserv4; /* 30-31 */
|
||||||
|
internal DBFField[] FieldArray { set; get; } /* each 32 bytes */
|
||||||
|
|
||||||
|
|
||||||
|
public DBFHeader()
|
||||||
|
{
|
||||||
|
Signature = DBFSignature.DBase3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal short Size => (short) (sizeof(byte) +
|
||||||
|
sizeof(byte) + sizeof(byte) + sizeof(byte) +
|
||||||
|
sizeof(int) +
|
||||||
|
sizeof(short) +
|
||||||
|
sizeof(short) +
|
||||||
|
sizeof(short) +
|
||||||
|
sizeof(byte) +
|
||||||
|
sizeof(byte) +
|
||||||
|
sizeof(int) +
|
||||||
|
sizeof(int) +
|
||||||
|
sizeof(int) +
|
||||||
|
sizeof(byte) +
|
||||||
|
sizeof(byte) +
|
||||||
|
sizeof(short) +
|
||||||
|
(DBFField.SIZE * FieldArray.Length) +
|
||||||
|
sizeof(byte));
|
||||||
|
|
||||||
|
internal short RecordSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var tRecordLength = 0;
|
||||||
|
for (var i = 0; i < FieldArray.Length; i++)
|
||||||
|
{
|
||||||
|
tRecordLength += FieldArray[i].FieldLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (short) (tRecordLength + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Read(BinaryReader dataInput)
|
||||||
|
{
|
||||||
|
Signature = dataInput.ReadByte(); /* 0 */
|
||||||
|
Year = dataInput.ReadByte(); /* 1 */
|
||||||
|
Month = dataInput.ReadByte(); /* 2 */
|
||||||
|
Day = dataInput.ReadByte(); /* 3 */
|
||||||
|
NumberOfRecords = dataInput.ReadInt32(); /* 4-7 */
|
||||||
|
|
||||||
|
HeaderLength = dataInput.ReadInt16(); /* 8-9 */
|
||||||
|
RecordLength = dataInput.ReadInt16(); /* 10-11 */
|
||||||
|
|
||||||
|
_reserv1 = dataInput.ReadInt16(); /* 12-13 */
|
||||||
|
_incompleteTransaction = dataInput.ReadByte(); /* 14 */
|
||||||
|
_encryptionFlag = dataInput.ReadByte(); /* 15 */
|
||||||
|
_freeRecordThread = dataInput.ReadInt32(); /* 16-19 */
|
||||||
|
_reserv2 = dataInput.ReadInt32(); /* 20-23 */
|
||||||
|
_reserv3 = dataInput.ReadInt32(); /* 24-27 */
|
||||||
|
_mdxFlag = dataInput.ReadByte(); /* 28 */
|
||||||
|
LanguageDriver = dataInput.ReadByte(); /* 29 */
|
||||||
|
_reserv4 = dataInput.ReadInt16(); /* 30-31 */
|
||||||
|
|
||||||
|
|
||||||
|
var v_fields = new List<DBFField>();
|
||||||
|
|
||||||
|
var field = DBFField.CreateField(dataInput); /* 32 each */
|
||||||
|
while (field != null)
|
||||||
|
{
|
||||||
|
v_fields.Add(field);
|
||||||
|
field = DBFField.CreateField(dataInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldArray = v_fields.ToArray();
|
||||||
|
//System.out.println( "Number of fields: " + _fieldArray.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Write(BinaryWriter dataOutput)
|
||||||
|
{
|
||||||
|
dataOutput.Write(Signature); /* 0 */
|
||||||
|
var tNow = DateTime.Now;
|
||||||
|
Year = (byte) (tNow.Year - 1900);
|
||||||
|
Month = (byte) (tNow.Month);
|
||||||
|
Day = (byte) (tNow.Day);
|
||||||
|
|
||||||
|
dataOutput.Write(Year); /* 1 */
|
||||||
|
dataOutput.Write(Month); /* 2 */
|
||||||
|
dataOutput.Write(Day); /* 3 */
|
||||||
|
|
||||||
|
//System.out.println( "Number of records in O/S: " + numberOfRecords);
|
||||||
|
dataOutput.Write(NumberOfRecords); /* 4-7 */
|
||||||
|
|
||||||
|
HeaderLength = Size;
|
||||||
|
dataOutput.Write(HeaderLength); /* 8-9 */
|
||||||
|
|
||||||
|
RecordLength = RecordSize;
|
||||||
|
dataOutput.Write(RecordLength); /* 10-11 */
|
||||||
|
|
||||||
|
dataOutput.Write(_reserv1); /* 12-13 */
|
||||||
|
dataOutput.Write(_incompleteTransaction); /* 14 */
|
||||||
|
dataOutput.Write(_encryptionFlag); /* 15 */
|
||||||
|
dataOutput.Write(_freeRecordThread); /* 16-19 */
|
||||||
|
dataOutput.Write(_reserv2); /* 20-23 */
|
||||||
|
dataOutput.Write(_reserv3); /* 24-27 */
|
||||||
|
|
||||||
|
dataOutput.Write(_mdxFlag); /* 28 */
|
||||||
|
dataOutput.Write(LanguageDriver); /* 29 */
|
||||||
|
dataOutput.Write(_reserv4); /* 30-31 */
|
||||||
|
|
||||||
|
foreach (var field in FieldArray)
|
||||||
|
{
|
||||||
|
field.Write(dataOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataOutput.Write(HeaderRecordTerminator); /* n+1 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
487
dotnetdbf/DBFReader.cs
Normal file
487
dotnetdbf/DBFReader.cs
Normal file
@@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
DBFReader
|
||||||
|
Class for reading the records assuming that the given
|
||||||
|
InputStream contains DBF data.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF package.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
|
||||||
|
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public class DBFReader : DBFBase, IDisposable
|
||||||
|
{
|
||||||
|
private BinaryReader _dataInputStream;
|
||||||
|
private DBFHeader _header;
|
||||||
|
private Stream _dataMemo;
|
||||||
|
|
||||||
|
private string _dataMemoLoc;
|
||||||
|
|
||||||
|
private int[] _selectFields = new int[] {};
|
||||||
|
private int[] _orderedSelectFields = new int[] {};
|
||||||
|
/* Class specific variables */
|
||||||
|
private bool _isClosed = true;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a DBFReader object.
|
||||||
|
|
||||||
|
When this constructor returns the object
|
||||||
|
will have completed reading the header (meta date) and
|
||||||
|
header information can be queried there on. And it will
|
||||||
|
be ready to return the first row.
|
||||||
|
|
||||||
|
@param InputStream where the data is read from.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public void SetSelectFields(params string[] aParams)
|
||||||
|
{
|
||||||
|
_selectFields =
|
||||||
|
aParams.Select(
|
||||||
|
it =>
|
||||||
|
Array.FindIndex(_header.FieldArray,
|
||||||
|
jt => jt.Name.Equals(it, StringComparison.OrdinalIgnoreCase))).ToArray();
|
||||||
|
_orderedSelectFields = _selectFields.OrderBy(it => it).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFField[] GetSelectFields()
|
||||||
|
{
|
||||||
|
return _selectFields.Any()
|
||||||
|
? _selectFields.Select(it => _header.FieldArray[it]).ToArray()
|
||||||
|
: _header.FieldArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DBFReader(string anIn)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_dataInputStream = new BinaryReader(
|
||||||
|
File.Open(anIn,
|
||||||
|
FileMode.Open,
|
||||||
|
FileAccess.Read,
|
||||||
|
FileShare.Read)
|
||||||
|
);
|
||||||
|
|
||||||
|
var dbtPath = Path.ChangeExtension(anIn, "dbt");
|
||||||
|
if (File.Exists(dbtPath))
|
||||||
|
{
|
||||||
|
_dataMemoLoc = dbtPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isClosed = false;
|
||||||
|
_header = new DBFHeader();
|
||||||
|
_header.Read(_dataInputStream);
|
||||||
|
|
||||||
|
/* it might be required to leap to the start of records at times */
|
||||||
|
var t_dataStartIndex = _header.HeaderLength
|
||||||
|
- (32 + (32 * _header.FieldArray.Length))
|
||||||
|
- 1;
|
||||||
|
if (t_dataStartIndex > 0)
|
||||||
|
{
|
||||||
|
_dataInputStream.ReadBytes((t_dataStartIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
throw new DBFException("Failed To Read DBF", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFReader(Stream anIn)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_dataInputStream = new BinaryReader(anIn);
|
||||||
|
_isClosed = false;
|
||||||
|
_header = new DBFHeader();
|
||||||
|
_header.Read(_dataInputStream);
|
||||||
|
|
||||||
|
/* it might be required to leap to the start of records at times */
|
||||||
|
var t_dataStartIndex = _header.HeaderLength
|
||||||
|
- (32 + (32 * _header.FieldArray.Length))
|
||||||
|
- 1;
|
||||||
|
if (t_dataStartIndex > 0)
|
||||||
|
{
|
||||||
|
_dataInputStream.ReadBytes((t_dataStartIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException("Failed To Read DBF", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of records in the DBF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public int RecordCount => _header.NumberOfRecords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the asked Field. In case of an invalid index,
|
||||||
|
it returns a ArrayIndexOutOfBoundsException.
|
||||||
|
|
||||||
|
@param index. Index of the field. Index of the first field is zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public DBFField[] Fields => _header.FieldArray;
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>Performs application-defined tasks associated with freeing, releasing,
|
||||||
|
/// or resetting unmanaged resources.</summary>
|
||||||
|
/// <filterpriority>2</filterpriority>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
public string DataMemoLoc
|
||||||
|
{
|
||||||
|
get => _dataMemoLoc;
|
||||||
|
set => _dataMemoLoc = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public delegate Stream LazyStream();
|
||||||
|
|
||||||
|
private Stream _loadedStream;
|
||||||
|
|
||||||
|
private LazyStream GetLazyStreamFromLocation()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_dataMemo == null && !string.IsNullOrEmpty(_dataMemoLoc))
|
||||||
|
{
|
||||||
|
return () => _loadedStream ??
|
||||||
|
(_loadedStream = File.Open(_dataMemoLoc, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read));
|
||||||
|
}
|
||||||
|
if (_dataMemo != null)
|
||||||
|
{
|
||||||
|
return () => _dataMemo;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream DataMemo
|
||||||
|
{
|
||||||
|
get => _dataMemo;
|
||||||
|
set => _dataMemo = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var sb =
|
||||||
|
new StringBuilder(_header.Year + "/" + _header.Month + "/"
|
||||||
|
+ _header.Day + "\n"
|
||||||
|
+ "Total records: " + _header.NumberOfRecords +
|
||||||
|
"\nHeader length: " + _header.HeaderLength +
|
||||||
|
"");
|
||||||
|
|
||||||
|
for (var i = 0; i < _header.FieldArray.Length; i++)
|
||||||
|
{
|
||||||
|
sb.Append(_header.FieldArray[i].Name);
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
_loadedStream?.Close();
|
||||||
|
_dataMemo?.Close();
|
||||||
|
_dataInputStream.Close();
|
||||||
|
|
||||||
|
_dataMemo?.Dispose();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_isClosed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads the returns the next row in the DBF stream.
|
||||||
|
@returns The next row as an Object array. Types of the elements
|
||||||
|
these arrays follow the convention mentioned in the class description.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public object[] NextRecord(bool throwOnParsingError = true)
|
||||||
|
{
|
||||||
|
return NextRecord(_selectFields, _orderedSelectFields, throwOnParsingError);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object[] NextRecord(IEnumerable<int> selectIndexes, IList<int> sortedIndexes, bool throwOnParsingError = true)
|
||||||
|
{
|
||||||
|
if (_isClosed)
|
||||||
|
{
|
||||||
|
throw new DBFException("Source is not open");
|
||||||
|
}
|
||||||
|
var tOrderdSelectIndexes = sortedIndexes;
|
||||||
|
|
||||||
|
var recordObjects = new object[_header.FieldArray.Length];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var isDeleted = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (isDeleted)
|
||||||
|
{
|
||||||
|
_dataInputStream.ReadBytes(_header.RecordLength - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int t_byte = _dataInputStream.ReadByte();
|
||||||
|
if (t_byte == DBFFieldType.EndOfData)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDeleted = (t_byte == '*');
|
||||||
|
} while (isDeleted);
|
||||||
|
|
||||||
|
var j = 0;
|
||||||
|
var k = -1;
|
||||||
|
for (var i = 0; i < _header.FieldArray.Length; i++)
|
||||||
|
{
|
||||||
|
if (tOrderdSelectIndexes.Count == j && j != 0
|
||||||
|
||
|
||||||
|
(tOrderdSelectIndexes.Count > j && tOrderdSelectIndexes[j] > i && tOrderdSelectIndexes[j] != k))
|
||||||
|
{
|
||||||
|
_dataInputStream.BaseStream.Seek(_header.FieldArray[i].FieldLength, SeekOrigin.Current);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tOrderdSelectIndexes.Count > j)
|
||||||
|
k = tOrderdSelectIndexes[j];
|
||||||
|
j++;
|
||||||
|
|
||||||
|
|
||||||
|
switch (_header.FieldArray[i].DataType)
|
||||||
|
{
|
||||||
|
case NativeDbType.Char:
|
||||||
|
|
||||||
|
var b_array = new byte[
|
||||||
|
_header.FieldArray[i].FieldLength
|
||||||
|
];
|
||||||
|
_dataInputStream.Read(b_array, 0, b_array.Length);
|
||||||
|
|
||||||
|
recordObjects[i] = CharEncoding.GetString(b_array).TrimEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Date:
|
||||||
|
|
||||||
|
var t_byte_year = new byte[4];
|
||||||
|
_dataInputStream.Read(t_byte_year,
|
||||||
|
0,
|
||||||
|
t_byte_year.Length);
|
||||||
|
|
||||||
|
var t_byte_month = new byte[2];
|
||||||
|
_dataInputStream.Read(t_byte_month,
|
||||||
|
0,
|
||||||
|
t_byte_month.Length);
|
||||||
|
|
||||||
|
var t_byte_day = new byte[2];
|
||||||
|
_dataInputStream.Read(t_byte_day,
|
||||||
|
0,
|
||||||
|
t_byte_day.Length);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tYear = CharEncoding.GetString(t_byte_year);
|
||||||
|
var tMonth = CharEncoding.GetString(t_byte_month);
|
||||||
|
var tDay = CharEncoding.GetString(t_byte_day);
|
||||||
|
|
||||||
|
if (int.TryParse(tYear, out var tIntYear) &&
|
||||||
|
int.TryParse(tMonth, out var tIntMonth) &&
|
||||||
|
int.TryParse(tDay, out var tIntDay))
|
||||||
|
{
|
||||||
|
recordObjects[i] = new DateTime(
|
||||||
|
tIntYear,
|
||||||
|
tIntMonth,
|
||||||
|
tIntDay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
/* this field may be empty or may have improper value set */
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Float:
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var t_float = new byte[
|
||||||
|
_header.FieldArray[i].FieldLength
|
||||||
|
];
|
||||||
|
_dataInputStream.Read(t_float, 0, t_float.Length);
|
||||||
|
var tParsed = CharEncoding.GetString(t_float);
|
||||||
|
var tLast = tParsed.Substring(tParsed.Length - 1);
|
||||||
|
if (tParsed.Length > 0
|
||||||
|
&& tLast != " "
|
||||||
|
&& tLast != NullSymbol)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// A Float in FoxPro has 20 significant digits, since it is
|
||||||
|
// stored as a string with possible E-postfix notation.
|
||||||
|
// An IEEE 754 float or double can not handle this number of digits
|
||||||
|
// correctly. Therefor the only correct implementation is to use a decimal.
|
||||||
|
//
|
||||||
|
recordObjects[i] = decimal.Parse(tParsed,
|
||||||
|
NumberStyles.Float | NumberStyles.AllowLeadingWhite,
|
||||||
|
NumberFormatInfo.InvariantInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FormatException e)
|
||||||
|
{
|
||||||
|
if (throwOnParsingError)
|
||||||
|
throw new DBFException("Failed to parse Float", e);
|
||||||
|
|
||||||
|
recordObjects[i] = default(decimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Numeric:
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var t_numeric = new byte[
|
||||||
|
_header.FieldArray[i].FieldLength
|
||||||
|
];
|
||||||
|
_dataInputStream.Read(t_numeric,
|
||||||
|
0,
|
||||||
|
t_numeric.Length);
|
||||||
|
var tParsed =
|
||||||
|
CharEncoding.GetString(t_numeric);
|
||||||
|
var tLast = tParsed.Substring(tParsed.Length - 1);
|
||||||
|
if (tParsed.Length > 0
|
||||||
|
&& tLast != " "
|
||||||
|
&& tLast != NullSymbol)
|
||||||
|
{
|
||||||
|
recordObjects[i] = decimal.Parse(tParsed,
|
||||||
|
NumberStyles.Float | NumberStyles.AllowLeadingWhite,
|
||||||
|
NumberFormatInfo.InvariantInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FormatException e)
|
||||||
|
{
|
||||||
|
if (throwOnParsingError)
|
||||||
|
throw new DBFException(
|
||||||
|
"Failed to parse Number", e);
|
||||||
|
|
||||||
|
recordObjects[i] = default(decimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
|
||||||
|
var t_logical = _dataInputStream.ReadByte();
|
||||||
|
//todo find out whats really valid
|
||||||
|
if (t_logical == 'Y' || t_logical == 't'
|
||||||
|
|| t_logical == 'T'
|
||||||
|
|| t_logical == 't')
|
||||||
|
{
|
||||||
|
recordObjects[i] = true;
|
||||||
|
}
|
||||||
|
else if (t_logical == DBFFieldType.UnknownByte)
|
||||||
|
{
|
||||||
|
recordObjects[i] = DBNull.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordObjects[i] = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
if (
|
||||||
|
|
||||||
|
string.IsNullOrEmpty(_dataMemoLoc) &&
|
||||||
|
|
||||||
|
_dataMemo is null)
|
||||||
|
{
|
||||||
|
throw new Exception("Memo Location Not Set");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var rawMemoPointer = _dataInputStream.ReadBytes(_header.FieldArray[i].FieldLength);
|
||||||
|
var memoPointer = CharEncoding.GetString(rawMemoPointer);
|
||||||
|
if (string.IsNullOrEmpty(memoPointer))
|
||||||
|
{
|
||||||
|
recordObjects[i] = DBNull.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!long.TryParse(memoPointer, out var tBlock))
|
||||||
|
{
|
||||||
|
//Because Memo files can vary and are often the least important data,
|
||||||
|
//we will return null when it doesn't match our format.
|
||||||
|
recordObjects[i] = DBNull.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
recordObjects[i] = new MemoValue(tBlock, this,
|
||||||
|
_dataMemoLoc,
|
||||||
|
GetLazyStreamFromLocation());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
byte[] data = _dataInputStream.ReadBytes(_header.FieldArray[i].FieldLength);
|
||||||
|
|
||||||
|
recordObjects[i] = data != null ? (object)data : DBNull.Value;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (EndOfStreamException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException("Problem Reading File", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectIndexes.Any() ? selectIndexes.Select(it => recordObjects[it]).ToArray() : recordObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
528
dotnetdbf/DBFWriter.cs
Normal file
528
dotnetdbf/DBFWriter.cs
Normal file
@@ -0,0 +1,528 @@
|
|||||||
|
/*
|
||||||
|
DBFWriter
|
||||||
|
Class for defining a DBF structure and addin data to that structure and
|
||||||
|
finally writing it to an OutputStream.
|
||||||
|
|
||||||
|
This file is part of DotNetDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public class DBFWriter : DBFBase, IDisposable
|
||||||
|
{
|
||||||
|
private DBFHeader header;
|
||||||
|
private Stream raf;
|
||||||
|
private int recordCount;
|
||||||
|
private List<object> v_records = new List<object>();
|
||||||
|
private Stream _dataMemo;
|
||||||
|
|
||||||
|
private string _dataMemoLoc;
|
||||||
|
|
||||||
|
/// Creates an empty Object.
|
||||||
|
public DBFWriter()
|
||||||
|
{
|
||||||
|
header = new DBFHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Creates a DBFWriter which can append to records to an existing DBF file.
|
||||||
|
/// @param dbfFile. The file passed in should be a valid DBF file.
|
||||||
|
/// @exception Throws DBFException if the passed in file does exist but not a valid DBF file, or if an IO error occurs.
|
||||||
|
public DBFWriter(string dbfFile)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
raf =
|
||||||
|
File.Open(dbfFile,
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite);
|
||||||
|
|
||||||
|
DataMemoLoc = Path.ChangeExtension(dbfFile, "dbt");
|
||||||
|
|
||||||
|
/* before proceeding check whether the passed in File object
|
||||||
|
is an empty/non-existent file or not.
|
||||||
|
*/
|
||||||
|
if (raf.Length == 0)
|
||||||
|
{
|
||||||
|
header = new DBFHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
header = new DBFHeader();
|
||||||
|
header.Read(new BinaryReader(raf));
|
||||||
|
|
||||||
|
/* position file pointer at the end of the raf */
|
||||||
|
raf.Seek(-1, SeekOrigin.End);
|
||||||
|
/* check whether the last byte is 0x1A (end of file marker for dbf files) - in this case move 1 byte back to ignore it when writing new records */
|
||||||
|
var lastByte = raf.ReadByte(); /* Advances to end of stream */
|
||||||
|
if (lastByte == DBFFieldType.EndOfData)
|
||||||
|
{
|
||||||
|
raf.Seek(-1, SeekOrigin.End);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new DBFException("Specified file is not found. ", e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException(" while reading header", e);
|
||||||
|
}
|
||||||
|
recordCount = header.NumberOfRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFWriter(Stream dbfFile)
|
||||||
|
{
|
||||||
|
raf = dbfFile;
|
||||||
|
|
||||||
|
/* before proceeding check whether the passed in File object
|
||||||
|
is an empty/non-existent file or not.
|
||||||
|
*/
|
||||||
|
if (raf.Length == 0)
|
||||||
|
{
|
||||||
|
header = new DBFHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
header = new DBFHeader();
|
||||||
|
header.Read(new BinaryReader(raf));
|
||||||
|
|
||||||
|
/* position file pointer at the end of the raf */
|
||||||
|
raf.Seek(-1, SeekOrigin.End);
|
||||||
|
/* check whether the last byte is 0x1A (end of file marker for dbf files) - in this case move 1 byte back to ignore it when writing new records */
|
||||||
|
var lastByte = raf.ReadByte(); /* Advances to end of stream */
|
||||||
|
if (lastByte == DBFFieldType.EndOfData)
|
||||||
|
{
|
||||||
|
raf.Seek(-1, SeekOrigin.End);
|
||||||
|
}
|
||||||
|
|
||||||
|
recordCount = header.NumberOfRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte Signature
|
||||||
|
{
|
||||||
|
get => header.Signature;
|
||||||
|
set => header.Signature = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string DataMemoLoc
|
||||||
|
{
|
||||||
|
get => _dataMemoLoc;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dataMemoLoc = value;
|
||||||
|
|
||||||
|
_dataMemo?.Close();
|
||||||
|
_dataMemo = File.Open(_dataMemoLoc,
|
||||||
|
FileMode.OpenOrCreate,
|
||||||
|
FileAccess.ReadWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream DataMemo
|
||||||
|
{
|
||||||
|
get => _dataMemo;
|
||||||
|
set => _dataMemo = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte LanguageDriver
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (header.LanguageDriver != 0x00)
|
||||||
|
{
|
||||||
|
throw new DBFException("LanguageDriver has already been set");
|
||||||
|
}
|
||||||
|
|
||||||
|
header.LanguageDriver = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DBFField[] Fields
|
||||||
|
{
|
||||||
|
get => header.FieldArray;
|
||||||
|
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (header.FieldArray != null)
|
||||||
|
{
|
||||||
|
throw new DBFException("Fields has already been set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null
|
||||||
|
|| value.Length == 0)
|
||||||
|
{
|
||||||
|
throw new DBFException("Should have at least one field");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < value.Length; i++)
|
||||||
|
{
|
||||||
|
if (value[i] == null)
|
||||||
|
{
|
||||||
|
throw new DBFException("Field " + (i + 1) + " is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FieldArray = value;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (raf != null
|
||||||
|
&& raf.Length == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
this is a new/non-existent file. So write header before proceeding
|
||||||
|
*/
|
||||||
|
header.Write(new BinaryWriter(raf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException("Error accessing file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>Performs application-defined tasks associated with freeing, releasing,
|
||||||
|
/// or resetting unmanaged resources.</summary>
|
||||||
|
/// <filterpriority>2</filterpriority>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add a record.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void WriteRecord(params object[] values)
|
||||||
|
{
|
||||||
|
if (raf == null)
|
||||||
|
{
|
||||||
|
throw new DBFException(
|
||||||
|
"Not initialized with file for WriteRecord use, use AddRecord instead");
|
||||||
|
}
|
||||||
|
AddRecord(values, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRecord(params object[] values)
|
||||||
|
{
|
||||||
|
if (raf != null)
|
||||||
|
{
|
||||||
|
throw new DBFException(
|
||||||
|
"Appending to a file, requires using WriteRecord instead");
|
||||||
|
}
|
||||||
|
AddRecord(values, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRecord(object[] values, bool writeImmediately)
|
||||||
|
{
|
||||||
|
if (header.FieldArray == null)
|
||||||
|
{
|
||||||
|
throw new DBFException(
|
||||||
|
"Fields should be set before adding records");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values == null)
|
||||||
|
{
|
||||||
|
throw new DBFException("Null cannot be added as row");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.Length
|
||||||
|
!= header.FieldArray.Length)
|
||||||
|
{
|
||||||
|
throw new DBFException(
|
||||||
|
"Invalid record. Invalid number of fields in row");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < header.FieldArray.Length; i++)
|
||||||
|
{
|
||||||
|
var fld = header.FieldArray[i];
|
||||||
|
var val = values[i];
|
||||||
|
|
||||||
|
if (val is null || val is DBNull)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThrowErrorIfNot<T>()
|
||||||
|
{
|
||||||
|
if (!(val is T))
|
||||||
|
{
|
||||||
|
throw new DBFRecordException($"Invalid value '{val}' for field {i}({fld.Name}{fld.DataType})", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fld.DataType)
|
||||||
|
{
|
||||||
|
case NativeDbType.Char:
|
||||||
|
//ignore all objects have ToString()
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
ThrowErrorIfNot<bool>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Numeric:
|
||||||
|
ThrowErrorIfNot<IConvertible>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Date:
|
||||||
|
ThrowErrorIfNot<DateTime>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Float:
|
||||||
|
ThrowErrorIfNot<IConvertible>();
|
||||||
|
break;
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
ThrowErrorIfNot<MemoValue>();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!writeImmediately)
|
||||||
|
{
|
||||||
|
v_records.Add(values);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WriteRecord(new BinaryWriter(raf), values);
|
||||||
|
recordCount++;
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException(
|
||||||
|
"Error occured while writing record. ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Writes the set data to the OutputStream.
|
||||||
|
public void Write(Stream tOut)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var outStream = new BinaryWriter(tOut);
|
||||||
|
|
||||||
|
header.NumberOfRecords = v_records.Count;
|
||||||
|
header.Write(outStream);
|
||||||
|
|
||||||
|
/* Now write all the records */
|
||||||
|
var t_recCount = v_records.Count;
|
||||||
|
for (var i = 0; i < t_recCount; i++)
|
||||||
|
{
|
||||||
|
/* iterate through records */
|
||||||
|
|
||||||
|
var t_values = (object[]) v_records[i];
|
||||||
|
|
||||||
|
WriteRecord(outStream, t_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
outStream.Write(DBFFieldType.EndOfData);
|
||||||
|
outStream.Flush();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new DBFException("Error Writing", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
/* everything is written already. just update the header for record count and the END_OF_DATA mark */
|
||||||
|
header.NumberOfRecords = recordCount;
|
||||||
|
if (raf != null)
|
||||||
|
{
|
||||||
|
raf.Seek(0, SeekOrigin.Begin);
|
||||||
|
header.Write(new BinaryWriter(raf));
|
||||||
|
raf.Seek(0, SeekOrigin.End);
|
||||||
|
raf.WriteByte(DBFFieldType.EndOfData);
|
||||||
|
|
||||||
|
raf.Close();
|
||||||
|
_dataMemo?.Close();
|
||||||
|
|
||||||
|
} else if (!string.IsNullOrEmpty(DataMemoLoc))
|
||||||
|
{
|
||||||
|
DataMemo.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteRecord(BinaryWriter dataOutput, object[] objectArray)
|
||||||
|
{
|
||||||
|
dataOutput.Write((byte) ' ');
|
||||||
|
for (var j = 0; j < header.FieldArray.Length; j++)
|
||||||
|
{
|
||||||
|
/* iterate through fields */
|
||||||
|
|
||||||
|
switch (header.FieldArray[j].DataType)
|
||||||
|
{
|
||||||
|
case NativeDbType.Char:
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
var str_value = objectArray[j].ToString();
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.textPadding(str_value,
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].
|
||||||
|
FieldLength
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.textPadding("",
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].
|
||||||
|
FieldLength
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Date:
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
var tDate = (DateTime) objectArray[j];
|
||||||
|
|
||||||
|
dataOutput.Write(
|
||||||
|
CharEncoding.GetBytes(tDate.ToString("yyyyMMdd")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.FillArray(new byte[8], DBFFieldType.Space));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Float:
|
||||||
|
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
var tDouble = Convert.ToDecimal(objectArray[j]);
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.NumericFormating(
|
||||||
|
tDouble,
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].FieldLength,
|
||||||
|
header.FieldArray[j].DecimalCount
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.textPadding(
|
||||||
|
NullSymbol,
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].FieldLength,
|
||||||
|
Utils.ALIGN_RIGHT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Numeric:
|
||||||
|
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
var tDecimal = Convert.ToDecimal(objectArray[j]);
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.NumericFormating(
|
||||||
|
tDecimal,
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].FieldLength,
|
||||||
|
header.FieldArray[j].DecimalCount
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.textPadding(
|
||||||
|
NullSymbol,
|
||||||
|
CharEncoding,
|
||||||
|
header.FieldArray[j].FieldLength,
|
||||||
|
Utils.ALIGN_RIGHT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
if ((bool) objectArray[j])
|
||||||
|
{
|
||||||
|
dataOutput.Write(DBFFieldType.True);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(DBFFieldType.False);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(DBFFieldType.UnknownByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
if (objectArray[j] != null && objectArray[j] != DBNull.Value)
|
||||||
|
{
|
||||||
|
var tMemoValue = ((MemoValue) objectArray[j]);
|
||||||
|
|
||||||
|
tMemoValue.Write(this);
|
||||||
|
|
||||||
|
dataOutput.Write(Utils.NumericFormating(tMemoValue.Block, CharEncoding, 10, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataOutput.Write(
|
||||||
|
Utils.textPadding("",
|
||||||
|
CharEncoding,
|
||||||
|
10
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new DBFException("Unknown field type "
|
||||||
|
+ header.FieldArray[j].DataType);
|
||||||
|
}
|
||||||
|
} /* iterating through the fields */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
dotnetdbf/DBTHeader.cs
Normal file
37
dotnetdbf/DBTHeader.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public class DBTHeader
|
||||||
|
{
|
||||||
|
public const byte FieldTerminator = 0x1A;
|
||||||
|
|
||||||
|
|
||||||
|
private int _nextBlock; /* 0-3*/
|
||||||
|
private byte _version = 0x03;
|
||||||
|
|
||||||
|
|
||||||
|
internal int NextBlock
|
||||||
|
{
|
||||||
|
get => _nextBlock;
|
||||||
|
set => _nextBlock = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal byte Version
|
||||||
|
{
|
||||||
|
get => _version;
|
||||||
|
set => _version = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Write(BinaryWriter dataOutput)
|
||||||
|
{
|
||||||
|
dataOutput.Write(_nextBlock);
|
||||||
|
dataOutput.Write(new byte[12]);
|
||||||
|
dataOutput.Write(_version);
|
||||||
|
dataOutput.Write(new byte[495]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
dotnetdbf/DotNetDBF.csproj
Normal file
33
dotnetdbf/DotNetDBF.csproj
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net35;netstandard2.0</TargetFrameworks>
|
||||||
|
<SignAssembly>True</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>sn.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<Version>7.0.0.0</Version>
|
||||||
|
<Company>Ekon Benefits</Company>
|
||||||
|
<Copyright>Copyright 2009-2017</Copyright>
|
||||||
|
<Description>This is a basic file parser for reading and writing xBase DBF files particularlly Clipper. Code originally derived from javadbf.</Description>
|
||||||
|
<PackageProjectUrl>https://github.com/ekonbenefits/dotnetdbf</PackageProjectUrl>
|
||||||
|
<PackageTags>clipper xbase dbf</PackageTags>
|
||||||
|
<Authors>Anil Kumar, Jay Tuley</Authors>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
<RepositoryUrl>https://github.com/ekonbenefits/dotnetdbf.git</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<IncludeSymbols>True</IncludeSymbols>
|
||||||
|
<IncludeSource>True</IncludeSource>
|
||||||
|
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
|
||||||
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="original java src\**" />
|
||||||
|
<EmbeddedResource Remove="original java src\**" />
|
||||||
|
<None Remove="original java src\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
33
dotnetdbf/DotNetDBF.sln
Normal file
33
dotnetdbf/DotNetDBF.sln
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.26228.9
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetDBF", "DotNetDBF\DotNetDBF.csproj", "{C5E9AE18-1EA3-4C90-AFAB-5323093BE4AC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetDBF.Enumerable", "DotNetDBF.Enumerable\DotNetDBF.Enumerable.csproj", "{3BB97ECD-325D-4288-B355-57CFC1404019}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetDBF.Test", "DotNetDBF.Test\DotNetDBF.Test.csproj", "{8D5436E3-F584-40A0-ACDC-65346ECEADB0}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C5E9AE18-1EA3-4C90-AFAB-5323093BE4AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C5E9AE18-1EA3-4C90-AFAB-5323093BE4AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C5E9AE18-1EA3-4C90-AFAB-5323093BE4AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C5E9AE18-1EA3-4C90-AFAB-5323093BE4AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3BB97ECD-325D-4288-B355-57CFC1404019}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BB97ECD-325D-4288-B355-57CFC1404019}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3BB97ECD-325D-4288-B355-57CFC1404019}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3BB97ECD-325D-4288-B355-57CFC1404019}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8D5436E3-F584-40A0-ACDC-65346ECEADB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8D5436E3-F584-40A0-ACDC-65346ECEADB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8D5436E3-F584-40A0-ACDC-65346ECEADB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8D5436E3-F584-40A0-ACDC-65346ECEADB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
9
dotnetdbf/DotNetDBF.sln.DotSettings
Normal file
9
dotnetdbf/DotNetDBF.sln.DotSettings
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DBT/@EntryIndexedValue">DBT</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue"><data><IncludeFilters /><ExcludeFilters /></data></s:String>
|
||||||
|
<s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue"><data /></s:String>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=javadbf/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=LGPL/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=reserv/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tuley/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
164
dotnetdbf/MemoValue.cs
Normal file
164
dotnetdbf/MemoValue.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public class MemoValue
|
||||||
|
{
|
||||||
|
public const string MemoTerminator = "\x1A";
|
||||||
|
private bool _loaded;
|
||||||
|
private bool _new;
|
||||||
|
|
||||||
|
|
||||||
|
public MemoValue(string aValue)
|
||||||
|
{
|
||||||
|
_lockName = $"DotNetDBF.Memo.new.{Guid.NewGuid()}";
|
||||||
|
Value = aValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal MemoValue(long block, DBFBase aBase,
|
||||||
|
string fileLoc, DBFReader.LazyStream fileStream)
|
||||||
|
{
|
||||||
|
_block = block;
|
||||||
|
_base = aBase;
|
||||||
|
_fileLoc = fileLoc;
|
||||||
|
_fileStream = fileStream;
|
||||||
|
if (string.IsNullOrEmpty(fileLoc))
|
||||||
|
{
|
||||||
|
_lockName = fileStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lockName = $"DotNetDBF.Memo.read.{_fileLoc}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DBFBase _base;
|
||||||
|
private readonly object _lockName;
|
||||||
|
private long _block;
|
||||||
|
private readonly string _fileLoc;
|
||||||
|
private string _value;
|
||||||
|
private readonly DBFReader.LazyStream _fileStream;
|
||||||
|
|
||||||
|
internal long Block => _block;
|
||||||
|
|
||||||
|
internal void Write(DBFWriter aBase)
|
||||||
|
{
|
||||||
|
lock (_lockName)
|
||||||
|
{
|
||||||
|
if (!_new)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var raf = aBase.DataMemo;
|
||||||
|
|
||||||
|
/* before proceeding check whether the passed in File object
|
||||||
|
is an empty/non-existent file or not.
|
||||||
|
*/
|
||||||
|
if (raf == null)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Null Memo Field Stream from Writer");
|
||||||
|
}
|
||||||
|
|
||||||
|
var tWriter = new BinaryWriter(raf, aBase.CharEncoding); //Don't close the stream could be used else where;
|
||||||
|
|
||||||
|
if (raf.Length == 0)
|
||||||
|
{
|
||||||
|
var tHeader = new DBTHeader();
|
||||||
|
tHeader.Write(tWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tValue = _value;
|
||||||
|
if ((tValue.Length + sizeof(int)) % aBase.BlockSize != 0)
|
||||||
|
{
|
||||||
|
tValue = tValue + MemoTerminator;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tPosition = raf.Seek(0, SeekOrigin.End); //Got To End Of File
|
||||||
|
var tBlockDiff = tPosition % aBase.BlockSize;
|
||||||
|
if (tBlockDiff != 0)
|
||||||
|
{
|
||||||
|
tPosition = raf.Seek(aBase.BlockSize - tBlockDiff, SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
_block = tPosition / aBase.BlockSize;
|
||||||
|
var tData = aBase.CharEncoding.GetBytes(tValue);
|
||||||
|
var tDataLength = tData.Length;
|
||||||
|
var tNewDiff = (tDataLength % aBase.BlockSize);
|
||||||
|
tWriter.Write(tData);
|
||||||
|
if (tNewDiff != 0)
|
||||||
|
tWriter.Seek(aBase.BlockSize - (tDataLength % aBase.BlockSize), SeekOrigin.Current);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lockName)
|
||||||
|
{
|
||||||
|
if (_new || _loaded) return _value;
|
||||||
|
var fileStream = _fileStream();
|
||||||
|
|
||||||
|
var reader = new BinaryReader(fileStream);
|
||||||
|
|
||||||
|
{
|
||||||
|
reader.BaseStream.Seek(_block * _base.BlockSize, SeekOrigin.Begin);
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
int termIndex;
|
||||||
|
var softReturn = _base.CharEncoding.GetString(new byte[] {0x8d, 0x0a});
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var data = reader.ReadBytes(_base.BlockSize);
|
||||||
|
if ((data.Length == 0))
|
||||||
|
{
|
||||||
|
throw new DBTException("Missing Data for block or no 1a memo terminator");
|
||||||
|
}
|
||||||
|
var stringVal = _base.CharEncoding.GetString(data);
|
||||||
|
termIndex = stringVal.IndexOf(MemoTerminator, StringComparison.Ordinal);
|
||||||
|
if (termIndex != -1)
|
||||||
|
stringVal = stringVal.Substring(0, termIndex);
|
||||||
|
builder.Append(stringVal);
|
||||||
|
} while (termIndex == -1);
|
||||||
|
_value = builder.ToString().Replace(softReturn, string.Empty);
|
||||||
|
}
|
||||||
|
_loaded = true;
|
||||||
|
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
lock (_lockName)
|
||||||
|
{
|
||||||
|
_new = true;
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return _lockName.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is MemoValue m)
|
||||||
|
{
|
||||||
|
return ReferenceEquals(this, obj) || Value.Equals(m.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
dotnetdbf/Properties/MoreAssemblyInfo.cs
Normal file
3
dotnetdbf/Properties/MoreAssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("DotNetDBF.Enumerable,PublicKey=00240000048000009400000006020000002400005253413100040000010001008713EA5197F8878AF1E1CDEF220E2D0A898944AD1643B851775EB8624697A183FBCD2ED8C1A58CE185B657D6381419AFF8B0DE8F8934F2B7E5DC7C19C11DE8D146B113F6794BF604BD2A11334DCF1022A485DD7A6E6BED8873D26363E9692136598B7750AD633747922657FF215347614DE2FDFA7866843F2924C9E5DB2545E1")]
|
||||||
11
dotnetdbf/README.md
Normal file
11
dotnetdbf/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
dotnetdbf
|
||||||
|
=========
|
||||||
|
|
||||||
|
This is a basic file parser written in C# for reading and writing xBase DBF files, particularly Clipper.
|
||||||
|
|
||||||
|
For .net 4.0 projects there is an enumeration framework in which makes it easy to use Linq to Objects.
|
||||||
|
|
||||||
|
Code derived from javadbf.
|
||||||
|
|
||||||
|
## Get The Binaries
|
||||||
|
Use [NuGet](http://nuget.org/packages/dotnetdbf/) from Visual Studio
|
||||||
175
dotnetdbf/Utils.cs
Normal file
175
dotnetdbf/Utils.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
Utils
|
||||||
|
Class for contining utility functions.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
original author (javadbf): anil@linuxense.com 2004/03/31
|
||||||
|
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
ported to C# (DotNetDBF): Jay Tuley <jay+dotnetdbf@tuley.name> 6/28/2007
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace DotNetDBF
|
||||||
|
{
|
||||||
|
public static class Utils
|
||||||
|
{
|
||||||
|
public const int ALIGN_LEFT = 10;
|
||||||
|
public const int ALIGN_RIGHT = 12;
|
||||||
|
|
||||||
|
public static byte[] FillArray(byte[] anArray, byte value)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < anArray.Length; i++)
|
||||||
|
{
|
||||||
|
anArray[i] = value;
|
||||||
|
}
|
||||||
|
return anArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] trimLeftSpaces(byte[] arr)
|
||||||
|
{
|
||||||
|
var tList = new List<byte>(arr.Length);
|
||||||
|
|
||||||
|
for (var i = 0; i < arr.Length; i++)
|
||||||
|
{
|
||||||
|
if (arr[i] != ' ')
|
||||||
|
{
|
||||||
|
tList.Add(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tList.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding(string text,
|
||||||
|
Encoding charEncoding,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
return textPadding(text, charEncoding, length, ALIGN_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding(string text,
|
||||||
|
Encoding charEncoding,
|
||||||
|
int length,
|
||||||
|
int alignment)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
textPadding(text,
|
||||||
|
charEncoding,
|
||||||
|
length,
|
||||||
|
alignment,
|
||||||
|
DBFFieldType.Space);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding(string text,
|
||||||
|
Encoding charEncoding,
|
||||||
|
int length,
|
||||||
|
int alignment,
|
||||||
|
byte paddingByte)
|
||||||
|
{
|
||||||
|
var tEncoding = charEncoding;
|
||||||
|
var inputBytes = tEncoding.GetBytes(text);
|
||||||
|
if (inputBytes.Length >= length)
|
||||||
|
{
|
||||||
|
return inputBytes.Take(length).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var byte_array = FillArray(new byte[length], paddingByte);
|
||||||
|
|
||||||
|
switch (alignment)
|
||||||
|
{
|
||||||
|
case ALIGN_LEFT:
|
||||||
|
Array.Copy(inputBytes,
|
||||||
|
0,
|
||||||
|
byte_array,
|
||||||
|
0,
|
||||||
|
inputBytes.Length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ALIGN_RIGHT:
|
||||||
|
var t_offset = length - text.Length;
|
||||||
|
Array.Copy(inputBytes,
|
||||||
|
0,
|
||||||
|
byte_array,
|
||||||
|
t_offset,
|
||||||
|
inputBytes.Length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return byte_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] NumericFormating(IFormattable doubleNum,
|
||||||
|
Encoding charEncoding,
|
||||||
|
int fieldLength,
|
||||||
|
int sizeDecimalPart)
|
||||||
|
{
|
||||||
|
var sizeWholePart = fieldLength
|
||||||
|
-
|
||||||
|
(sizeDecimalPart > 0 ? (sizeDecimalPart + 1) : 0);
|
||||||
|
|
||||||
|
var format = new StringBuilder(fieldLength);
|
||||||
|
|
||||||
|
for (var i = 0; i < sizeWholePart; i++)
|
||||||
|
{
|
||||||
|
format.Append(i + 1 == sizeWholePart ? "0" : "#");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeDecimalPart > 0)
|
||||||
|
{
|
||||||
|
format.Append(".");
|
||||||
|
|
||||||
|
for (var i = 0; i < sizeDecimalPart; i++)
|
||||||
|
{
|
||||||
|
format.Append("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
textPadding(
|
||||||
|
doubleNum.ToString(format.ToString(),
|
||||||
|
NumberFormatInfo.InvariantInfo),
|
||||||
|
charEncoding,
|
||||||
|
fieldLength,
|
||||||
|
ALIGN_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool contains(byte[] arr, byte value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
Array.Exists(arr,
|
||||||
|
delegate(byte anItem) { return anItem == value; });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Type TypeForNativeDBType(NativeDbType aType)
|
||||||
|
{
|
||||||
|
switch (aType)
|
||||||
|
{
|
||||||
|
case NativeDbType.Char:
|
||||||
|
return typeof(string);
|
||||||
|
case NativeDbType.Date:
|
||||||
|
return typeof(DateTime);
|
||||||
|
case NativeDbType.Numeric:
|
||||||
|
return typeof(decimal);
|
||||||
|
case NativeDbType.Logical:
|
||||||
|
return typeof(bool);
|
||||||
|
case NativeDbType.Float:
|
||||||
|
return typeof(decimal);
|
||||||
|
case NativeDbType.Memo:
|
||||||
|
return typeof(MemoValue);
|
||||||
|
default:
|
||||||
|
return typeof(Object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
dotnetdbf/original java src/DBFBase.java
Normal file
36
dotnetdbf/original java src/DBFBase.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
$Id: DBFBase.java,v 1.3 2004/03/31 15:59:40 anil Exp $
|
||||||
|
Serves as the base class of DBFReader adn DBFWriter.
|
||||||
|
|
||||||
|
@author: anil@linuxense.com
|
||||||
|
|
||||||
|
Support for choosing implemented character Sets as
|
||||||
|
suggested by Nick Voznesensky <darkers@mail.ru>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
Base class for DBFReader and DBFWriter.
|
||||||
|
*/
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
|
||||||
|
public abstract class DBFBase {
|
||||||
|
|
||||||
|
protected String characterSetName = "8859_1";
|
||||||
|
protected final int END_OF_DATA = 0x1A;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the library is used in a non-latin environment use this method to set
|
||||||
|
corresponding character set. More information:
|
||||||
|
http://www.iana.org/assignments/character-sets
|
||||||
|
Also see the documentation of the class java.nio.charset.Charset
|
||||||
|
*/
|
||||||
|
public String getCharactersetName() {
|
||||||
|
|
||||||
|
return this.characterSetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCharactersetName( String characterSetName) {
|
||||||
|
|
||||||
|
this.characterSetName = characterSetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
27
dotnetdbf/original java src/DBFException.java
Normal file
27
dotnetdbf/original java src/DBFException.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
DBFException
|
||||||
|
Represents exceptions happen in the JAvaDBF classes.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
author: anil@linuxense.com
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id: DBFException.java,v 1.2 2004/03/31 10:40:18 anil Exp $
|
||||||
|
*/
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DBFException extends IOException {
|
||||||
|
|
||||||
|
public DBFException() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBFException( String msg) {
|
||||||
|
|
||||||
|
super( msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
283
dotnetdbf/original java src/DBFField.java
Normal file
283
dotnetdbf/original java src/DBFField.java
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
DBFField
|
||||||
|
Class represents a "field" (or column) definition of a DBF data structure.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
author: anil@linuxense.com
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id: DBFField.java,v 1.7 2004/03/31 10:50:11 anil Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
DBFField represents a field specification in an dbf file.
|
||||||
|
|
||||||
|
DBFField objects are either created and added to a DBFWriter object or obtained
|
||||||
|
from DBFReader object through getField( int) query.
|
||||||
|
|
||||||
|
*/
|
||||||
|
public class DBFField {
|
||||||
|
|
||||||
|
public static final byte FIELD_TYPE_C = (byte)'C';
|
||||||
|
public static final byte FIELD_TYPE_L = (byte)'L';
|
||||||
|
public static final byte FIELD_TYPE_N = (byte)'N';
|
||||||
|
public static final byte FIELD_TYPE_F = (byte)'F';
|
||||||
|
public static final byte FIELD_TYPE_D = (byte)'D';
|
||||||
|
public static final byte FIELD_TYPE_M = (byte)'M';
|
||||||
|
|
||||||
|
/* Field struct variables start here */
|
||||||
|
byte[] fieldName = new byte[ 11]; /* 0-10*/
|
||||||
|
byte dataType; /* 11 */
|
||||||
|
int reserv1; /* 12-15 */
|
||||||
|
int fieldLength; /* 16 */
|
||||||
|
byte decimalCount; /* 17 */
|
||||||
|
short reserv2; /* 18-19 */
|
||||||
|
byte workAreaId; /* 20 */
|
||||||
|
short reserv3; /* 21-22 */
|
||||||
|
byte setFieldsFlag; /* 23 */
|
||||||
|
byte[] reserv4 = new byte[ 7]; /* 24-30 */
|
||||||
|
byte indexFieldFlag; /* 31 */
|
||||||
|
/* Field struct variables end here */
|
||||||
|
|
||||||
|
/* other class variables */
|
||||||
|
int nameNullIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a DBFField object from the data read from the given DataInputStream.
|
||||||
|
|
||||||
|
The data in the DataInputStream object is supposed to be organised correctly
|
||||||
|
and the stream "pointer" is supposed to be positioned properly.
|
||||||
|
|
||||||
|
@param in DataInputStream
|
||||||
|
@return Returns the created DBFField object.
|
||||||
|
@throws IOException If any stream reading problems occures.
|
||||||
|
*/
|
||||||
|
protected static DBFField createField( DataInput in)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
DBFField field = new DBFField();
|
||||||
|
|
||||||
|
byte t_byte = in.readByte(); /* 0 */
|
||||||
|
if( t_byte == (byte)0x0d) {
|
||||||
|
|
||||||
|
//System.out.println( "End of header found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.readFully( field.fieldName, 1, 10); /* 1-10 */
|
||||||
|
field.fieldName[0] = t_byte;
|
||||||
|
|
||||||
|
for( int i=0; i<field.fieldName.length; i++) {
|
||||||
|
|
||||||
|
if( field.fieldName[ i] == (byte)0) {
|
||||||
|
|
||||||
|
field.nameNullIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field.dataType = in.readByte(); /* 11 */
|
||||||
|
field.reserv1 = Utils.readLittleEndianInt( in); /* 12-15 */
|
||||||
|
field.fieldLength = in.readUnsignedByte(); /* 16 */
|
||||||
|
field.decimalCount = in.readByte(); /* 17 */
|
||||||
|
field.reserv2 = Utils.readLittleEndianShort( in); /* 18-19 */
|
||||||
|
field.workAreaId = in.readByte(); /* 20 */
|
||||||
|
field.reserv2 = Utils.readLittleEndianShort( in); /* 21-22 */
|
||||||
|
field.setFieldsFlag = in.readByte(); /* 23 */
|
||||||
|
in.readFully( field.reserv4); /* 24-30 */
|
||||||
|
field.indexFieldFlag = in.readByte(); /* 31 */
|
||||||
|
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes the content of DBFField object into the stream as per
|
||||||
|
DBF format specifications.
|
||||||
|
|
||||||
|
@param os OutputStream
|
||||||
|
@throws IOException if any stream related issues occur.
|
||||||
|
*/
|
||||||
|
protected void write( DataOutput out)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
//DataOutputStream out = new DataOutputStream( os);
|
||||||
|
|
||||||
|
// Field Name
|
||||||
|
out.write( fieldName); /* 0-10 */
|
||||||
|
out.write( new byte[ 11 - fieldName.length]);
|
||||||
|
|
||||||
|
// data type
|
||||||
|
out.writeByte( dataType); /* 11 */
|
||||||
|
out.writeInt( 0x00); /* 12-15 */
|
||||||
|
out.writeByte( fieldLength); /* 16 */
|
||||||
|
out.writeByte( decimalCount); /* 17 */
|
||||||
|
out.writeShort( (short)0x00); /* 18-19 */
|
||||||
|
out.writeByte( (byte)0x00); /* 20 */
|
||||||
|
out.writeShort( (short)0x00); /* 21-22 */
|
||||||
|
out.writeByte( (byte)0x00); /* 23 */
|
||||||
|
out.write( new byte[7]); /* 24-30*/
|
||||||
|
out.writeByte( (byte)0x00); /* 31 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the name of the field.
|
||||||
|
|
||||||
|
@return Name of the field as String.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
|
||||||
|
return new String( this.fieldName, 0, nameNullIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the data type of the field.
|
||||||
|
|
||||||
|
@return Data type as byte.
|
||||||
|
*/
|
||||||
|
public byte getDataType() {
|
||||||
|
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns field length.
|
||||||
|
|
||||||
|
@return field length as int.
|
||||||
|
*/
|
||||||
|
public int getFieldLength() {
|
||||||
|
|
||||||
|
return fieldLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the decimal part. This is applicable
|
||||||
|
only if the field type if of numeric in nature.
|
||||||
|
|
||||||
|
If the field is specified to hold integral values
|
||||||
|
the value returned by this method will be zero.
|
||||||
|
|
||||||
|
@return decimal field size as int.
|
||||||
|
*/
|
||||||
|
public int getDecimalCount() {
|
||||||
|
|
||||||
|
return decimalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setter methods
|
||||||
|
|
||||||
|
// byte[] fieldName = new byte[ 11]; /* 0-10*/
|
||||||
|
// byte dataType; /* 11 */
|
||||||
|
// int reserv1; /* 12-15 */
|
||||||
|
// byte fieldLength; /* 16 */
|
||||||
|
// byte decimalCount; /* 17 */
|
||||||
|
// short reserv2; /* 18-19 */
|
||||||
|
// byte workAreaId; /* 20 */
|
||||||
|
// short reserv3; /* 21-22 */
|
||||||
|
// byte setFieldsFlag; /* 23 */
|
||||||
|
// byte[] reserv4 = new byte[ 7]; /* 24-30 */
|
||||||
|
// byte indexFieldFlag; /* 31 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This method is depricated as of version 0.3.3.1 and is replaced by {@link #setName( String)}.
|
||||||
|
*/
|
||||||
|
public void setFieldName( String value) {
|
||||||
|
|
||||||
|
setName( value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the name of the field.
|
||||||
|
|
||||||
|
@param name of the field as String.
|
||||||
|
@since 0.3.3.1
|
||||||
|
*/
|
||||||
|
public void setName( String value) {
|
||||||
|
|
||||||
|
if( value == null) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Field name cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value.length() == 0 || value.length() > 10) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Field name should be of length 0-10");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fieldName = value.getBytes();
|
||||||
|
this.nameNullIndex = this.fieldName.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the data type of the field.
|
||||||
|
|
||||||
|
@param type of the field. One of the following:<br>
|
||||||
|
C, L, N, F, D, M
|
||||||
|
*/
|
||||||
|
public void setDataType( byte value) {
|
||||||
|
|
||||||
|
switch( value) {
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
this.fieldLength = 8; /* fall through */
|
||||||
|
case 'C':
|
||||||
|
case 'L':
|
||||||
|
case 'N':
|
||||||
|
case 'F':
|
||||||
|
case 'M':
|
||||||
|
|
||||||
|
this.dataType = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException( "Unknown data type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Length of the field.
|
||||||
|
This method should be called before calling setDecimalCount().
|
||||||
|
|
||||||
|
@param Length of the field as int.
|
||||||
|
*/
|
||||||
|
public void setFieldLength( int value) {
|
||||||
|
|
||||||
|
if( value <= 0) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Field length should be a positive number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.dataType == FIELD_TYPE_D) {
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException( "Cannot do this on a Date field");
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldLength = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the decimal place size of the field.
|
||||||
|
Before calling this method the size of the field
|
||||||
|
should be set by calling setFieldLength().
|
||||||
|
|
||||||
|
@param Size of the decimal field.
|
||||||
|
*/
|
||||||
|
public void setDecimalCount( int value) {
|
||||||
|
|
||||||
|
if( value < 0) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Decimal length should be a positive number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value > fieldLength) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Decimal length should be less than field length");
|
||||||
|
}
|
||||||
|
|
||||||
|
decimalCount = (byte)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
167
dotnetdbf/original java src/DBFHeader.java
Normal file
167
dotnetdbf/original java src/DBFHeader.java
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
DBFHeader
|
||||||
|
Class for reading the metadata assuming that the given
|
||||||
|
InputStream carries DBF data.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
Author: anil@linuxense.com
|
||||||
|
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
class DBFHeader {
|
||||||
|
|
||||||
|
static final byte SIG_DBASE_III = (byte)0x03;
|
||||||
|
/* DBF structure start here */
|
||||||
|
|
||||||
|
byte signature; /* 0 */
|
||||||
|
byte year; /* 1 */
|
||||||
|
byte month; /* 2 */
|
||||||
|
byte day; /* 3 */
|
||||||
|
int numberOfRecords; /* 4-7 */
|
||||||
|
short headerLength; /* 8-9 */
|
||||||
|
short recordLength; /* 10-11 */
|
||||||
|
short reserv1; /* 12-13 */
|
||||||
|
byte incompleteTransaction; /* 14 */
|
||||||
|
byte encryptionFlag; /* 15 */
|
||||||
|
int freeRecordThread; /* 16-19 */
|
||||||
|
int reserv2; /* 20-23 */
|
||||||
|
int reserv3; /* 24-27 */
|
||||||
|
byte mdxFlag; /* 28 */
|
||||||
|
byte languageDriver; /* 29 */
|
||||||
|
short reserv4; /* 30-31 */
|
||||||
|
DBFField []fieldArray; /* each 32 bytes */
|
||||||
|
byte terminator1; /* n+1 */
|
||||||
|
|
||||||
|
//byte[] databaseContainer; /* 263 bytes */
|
||||||
|
/* DBF structure ends here */
|
||||||
|
|
||||||
|
DBFHeader() {
|
||||||
|
|
||||||
|
this.signature = SIG_DBASE_III;
|
||||||
|
this.terminator1 = 0x0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read( DataInput dataInput) throws IOException {
|
||||||
|
|
||||||
|
signature = dataInput.readByte(); /* 0 */
|
||||||
|
year = dataInput.readByte(); /* 1 */
|
||||||
|
month = dataInput.readByte(); /* 2 */
|
||||||
|
day = dataInput.readByte(); /* 3 */
|
||||||
|
numberOfRecords = Utils.readLittleEndianInt( dataInput); /* 4-7 */
|
||||||
|
|
||||||
|
headerLength = Utils.readLittleEndianShort( dataInput); /* 8-9 */
|
||||||
|
recordLength = Utils.readLittleEndianShort( dataInput); /* 10-11 */
|
||||||
|
|
||||||
|
reserv1 = Utils.readLittleEndianShort( dataInput); /* 12-13 */
|
||||||
|
incompleteTransaction = dataInput.readByte(); /* 14 */
|
||||||
|
encryptionFlag = dataInput.readByte(); /* 15 */
|
||||||
|
freeRecordThread = Utils.readLittleEndianInt( dataInput); /* 16-19 */
|
||||||
|
reserv2 = dataInput.readInt(); /* 20-23 */
|
||||||
|
reserv3 = dataInput.readInt(); /* 24-27 */
|
||||||
|
mdxFlag = dataInput.readByte(); /* 28 */
|
||||||
|
languageDriver = dataInput.readByte(); /* 29 */
|
||||||
|
reserv4 = Utils.readLittleEndianShort( dataInput); /* 30-31 */
|
||||||
|
|
||||||
|
Vector v_fields = new Vector();
|
||||||
|
|
||||||
|
DBFField field = DBFField.createField( dataInput); /* 32 each */
|
||||||
|
while( field != null) {
|
||||||
|
|
||||||
|
v_fields.addElement( field);
|
||||||
|
field = DBFField.createField( dataInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldArray = new DBFField[ v_fields.size()];
|
||||||
|
|
||||||
|
for( int i=0; i<fieldArray.length; i++) {
|
||||||
|
|
||||||
|
fieldArray[ i] = (DBFField)v_fields.elementAt( i);
|
||||||
|
}
|
||||||
|
//System.out.println( "Number of fields: " + fieldArray.length);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void write( DataOutput dataOutput) throws IOException {
|
||||||
|
|
||||||
|
dataOutput.writeByte( signature); /* 0 */
|
||||||
|
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar();
|
||||||
|
year = (byte)( calendar.get( Calendar.YEAR) - 1900);
|
||||||
|
month = (byte)( calendar.get( Calendar.MONTH)+1);
|
||||||
|
day = (byte)( calendar.get( Calendar.DAY_OF_MONTH));
|
||||||
|
|
||||||
|
dataOutput.writeByte( year); /* 1 */
|
||||||
|
dataOutput.writeByte( month); /* 2 */
|
||||||
|
dataOutput.writeByte( day); /* 3 */
|
||||||
|
|
||||||
|
//System.out.println( "Number of records in O/S: " + numberOfRecords);
|
||||||
|
numberOfRecords = Utils.littleEndian( numberOfRecords);
|
||||||
|
dataOutput.writeInt( numberOfRecords); /* 4-7 */
|
||||||
|
|
||||||
|
headerLength = findHeaderLength();
|
||||||
|
dataOutput.writeShort( Utils.littleEndian( headerLength)); /* 8-9 */
|
||||||
|
|
||||||
|
recordLength = findRecordLength();
|
||||||
|
dataOutput.writeShort( Utils.littleEndian( recordLength)); /* 10-11 */
|
||||||
|
|
||||||
|
dataOutput.writeShort( Utils.littleEndian( reserv1)); /* 12-13 */
|
||||||
|
dataOutput.writeByte( incompleteTransaction); /* 14 */
|
||||||
|
dataOutput.writeByte( encryptionFlag); /* 15 */
|
||||||
|
dataOutput.writeInt( Utils.littleEndian( freeRecordThread));/* 16-19 */
|
||||||
|
dataOutput.writeInt( Utils.littleEndian( reserv2)); /* 20-23 */
|
||||||
|
dataOutput.writeInt( Utils.littleEndian( reserv3)); /* 24-27 */
|
||||||
|
|
||||||
|
dataOutput.writeByte( mdxFlag); /* 28 */
|
||||||
|
dataOutput.writeByte( languageDriver); /* 29 */
|
||||||
|
dataOutput.writeShort( Utils.littleEndian( reserv4)); /* 30-31 */
|
||||||
|
|
||||||
|
for( int i=0; i<fieldArray.length; i++) {
|
||||||
|
|
||||||
|
//System.out.println( "Length: " + fieldArray[i].getFieldLength());
|
||||||
|
fieldArray[i].write( dataOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataOutput.writeByte( terminator1); /* n+1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
private short findHeaderLength() {
|
||||||
|
|
||||||
|
return (short)(
|
||||||
|
1+
|
||||||
|
3+
|
||||||
|
4+
|
||||||
|
2+
|
||||||
|
2+
|
||||||
|
2+
|
||||||
|
1+
|
||||||
|
1+
|
||||||
|
4+
|
||||||
|
4+
|
||||||
|
4+
|
||||||
|
1+
|
||||||
|
1+
|
||||||
|
2+
|
||||||
|
(32*fieldArray.length)+
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private short findRecordLength() {
|
||||||
|
|
||||||
|
int recordLength = 0;
|
||||||
|
for( int i=0; i<fieldArray.length; i++) {
|
||||||
|
|
||||||
|
recordLength += fieldArray[i].getFieldLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (short)(recordLength + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
315
dotnetdbf/original java src/DBFReader.java
Normal file
315
dotnetdbf/original java src/DBFReader.java
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
DBFReader
|
||||||
|
Class for reading the records assuming that the given
|
||||||
|
InputStream comtains DBF data.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
Author: anil@linuxense.com
|
||||||
|
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id: DBFReader.java,v 1.8 2004/03/31 10:54:03 anil Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
DBFReader class can creates objects to represent DBF data.
|
||||||
|
|
||||||
|
This Class is used to read data from a DBF file. Meta data and
|
||||||
|
records can be queried against this document.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
DBFReader cannot write anythng to a DBF file. For creating DBF files
|
||||||
|
use DBFWriter.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Fetching rocord is possible only in the forward direction and
|
||||||
|
cannot re-wound. In such situation, a suggested approach is to reconstruct the object.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The nextRecord() method returns an array of Objects and the types of these
|
||||||
|
Object are as follows:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>xBase Type</th><th>Java Type</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>C</td><td>String</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>N</td><td>Integer</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>F</td><td>Double</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>L</td><td>Boolean</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>D</td><td>java.util.Date</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
*/
|
||||||
|
public class DBFReader extends DBFBase {
|
||||||
|
|
||||||
|
DataInputStream dataInputStream;
|
||||||
|
DBFHeader header;
|
||||||
|
|
||||||
|
/* Class specific variables */
|
||||||
|
boolean isClosed = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a DBFReader object.
|
||||||
|
|
||||||
|
When this constructor returns the object
|
||||||
|
will have completed reading the hader (meta date) and
|
||||||
|
header information can be quried there on. And it will
|
||||||
|
be ready to return the first row.
|
||||||
|
|
||||||
|
@param InputStream where the data is read from.
|
||||||
|
*/
|
||||||
|
public DBFReader( InputStream in) throws DBFException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
this.dataInputStream = new DataInputStream( in);
|
||||||
|
this.isClosed = false;
|
||||||
|
this.header = new DBFHeader();
|
||||||
|
this.header.read( this.dataInputStream);
|
||||||
|
|
||||||
|
/* it might be required to leap to the start of records at times */
|
||||||
|
int t_dataStartIndex = this.header.headerLength - ( 32 + (32*this.header.fieldArray.length)) - 1;
|
||||||
|
if( t_dataStartIndex > 0) {
|
||||||
|
|
||||||
|
dataInputStream.skip( t_dataStartIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
StringBuffer sb = new StringBuffer( this.header.year + "/" + this.header.month + "/" + this.header.day + "\n"
|
||||||
|
+ "Total records: " + this.header.numberOfRecords +
|
||||||
|
"\nHEader length: " + this.header.headerLength +
|
||||||
|
"");
|
||||||
|
|
||||||
|
for( int i=0; i<this.header.fieldArray.length; i++) {
|
||||||
|
|
||||||
|
sb.append( this.header.fieldArray[i].getName());
|
||||||
|
sb.append( "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of records in the DBF.
|
||||||
|
*/
|
||||||
|
public int getRecordCount() {
|
||||||
|
|
||||||
|
return this.header.numberOfRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the asked Field. In case of an invalid index,
|
||||||
|
it returns a ArrayIndexOutofboundsException.
|
||||||
|
|
||||||
|
@param index. Index of the field. Index of the first field is zero.
|
||||||
|
*/
|
||||||
|
public DBFField getField( int index)
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
if( isClosed) {
|
||||||
|
|
||||||
|
throw new DBFException( "Source is not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.header.fieldArray[ index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of field in the DBF.
|
||||||
|
*/
|
||||||
|
public int getFieldCount()
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
if( isClosed) {
|
||||||
|
|
||||||
|
throw new DBFException( "Source is not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.header.fieldArray != null) {
|
||||||
|
|
||||||
|
return this.header.fieldArray.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads the returns the next row in the DBF stream.
|
||||||
|
@returns The next row as an Object array. Types of the elements
|
||||||
|
these arrays follow the convention mentioned in the class description.
|
||||||
|
*/
|
||||||
|
public Object[] nextRecord()
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
if( isClosed) {
|
||||||
|
|
||||||
|
throw new DBFException( "Source is not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object recordObjects[] = new Object[ this.header.fieldArray.length];
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
boolean isDeleted = false;
|
||||||
|
do {
|
||||||
|
|
||||||
|
if( isDeleted) {
|
||||||
|
|
||||||
|
dataInputStream.skip( this.header.recordLength-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int t_byte = dataInputStream.readByte();
|
||||||
|
if( t_byte == END_OF_DATA) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDeleted = ( t_byte == '*');
|
||||||
|
} while( isDeleted);
|
||||||
|
|
||||||
|
for( int i=0; i<this.header.fieldArray.length; i++) {
|
||||||
|
|
||||||
|
switch( this.header.fieldArray[i].getDataType()) {
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
|
||||||
|
byte b_array[] = new byte[ this.header.fieldArray[i].getFieldLength()];
|
||||||
|
dataInputStream.read( b_array);
|
||||||
|
recordObjects[i] = new String( b_array, characterSetName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
|
||||||
|
byte t_byte_year[] = new byte[ 4];
|
||||||
|
dataInputStream.read( t_byte_year);
|
||||||
|
|
||||||
|
byte t_byte_month[] = new byte[ 2];
|
||||||
|
dataInputStream.read( t_byte_month);
|
||||||
|
|
||||||
|
byte t_byte_day[] = new byte[ 2];
|
||||||
|
dataInputStream.read( t_byte_day);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar(
|
||||||
|
Integer.parseInt( new String( t_byte_year)),
|
||||||
|
Integer.parseInt( new String( t_byte_month)) - 1,
|
||||||
|
Integer.parseInt( new String( t_byte_day))
|
||||||
|
);
|
||||||
|
|
||||||
|
recordObjects[i] = calendar.getTime();
|
||||||
|
}
|
||||||
|
catch ( NumberFormatException e) {
|
||||||
|
/* this field may be empty or may have improper value set */
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
byte t_float[] = new byte[ this.header.fieldArray[i].getFieldLength()];
|
||||||
|
dataInputStream.read( t_float);
|
||||||
|
t_float = Utils.trimLeftSpaces( t_float);
|
||||||
|
if( t_float.length > 0 && !Utils.contains( t_float, (byte)'?')) {
|
||||||
|
|
||||||
|
recordObjects[i] = new Float( new String( t_float));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e) {
|
||||||
|
|
||||||
|
throw new DBFException( "Failed to parse Float: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
byte t_numeric[] = new byte[ this.header.fieldArray[i].getFieldLength()];
|
||||||
|
dataInputStream.read( t_numeric);
|
||||||
|
t_numeric = Utils.trimLeftSpaces( t_numeric);
|
||||||
|
|
||||||
|
if( t_numeric.length > 0 && !Utils.contains( t_numeric, (byte)'?')) {
|
||||||
|
|
||||||
|
recordObjects[i] = new Double( new String( t_numeric));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
recordObjects[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e) {
|
||||||
|
|
||||||
|
throw new DBFException( "Failed to parse Number: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
|
||||||
|
byte t_logical = dataInputStream.readByte();
|
||||||
|
if( t_logical == 'Y' || t_logical == 't' || t_logical == 'T' || t_logical == 't') {
|
||||||
|
|
||||||
|
recordObjects[i] = Boolean.TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
recordObjects[i] = Boolean.FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M':
|
||||||
|
// TODO Later
|
||||||
|
recordObjects[i] = new String( "null");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
recordObjects[i] = new String( "null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( EOFException e) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return recordObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
350
dotnetdbf/original java src/DBFWriter.java
Normal file
350
dotnetdbf/original java src/DBFWriter.java
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
/*
|
||||||
|
DBFWriter
|
||||||
|
Class for defining a DBF structure and addin data to that structure and
|
||||||
|
finally writing it to an OutputStream.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
author: anil@linuxense.com
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id: DBFWriter.java,v 1.9 2004/03/31 10:57:16 anil Exp $
|
||||||
|
*/
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
An object of this class can create a DBF file.
|
||||||
|
|
||||||
|
Create an object, <br>
|
||||||
|
then define fields by creating DBFField objects and<br>
|
||||||
|
add them to the DBFWriter object<br>
|
||||||
|
add records using the addRecord() method and then<br>
|
||||||
|
call write() method.
|
||||||
|
*/
|
||||||
|
public class DBFWriter extends DBFBase {
|
||||||
|
|
||||||
|
/* other class variables */
|
||||||
|
DBFHeader header;
|
||||||
|
Vector v_records = new Vector();
|
||||||
|
int recordCount = 0;
|
||||||
|
RandomAccessFile raf = null; /* Open and append records to an existing DBF */
|
||||||
|
boolean appendMode = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates an empty Object.
|
||||||
|
*/
|
||||||
|
public DBFWriter() {
|
||||||
|
|
||||||
|
this.header = new DBFHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a DBFWriter which can append to records to an existing DBF file.
|
||||||
|
@param dbfFile. The file passed in shouls be a valid DBF file.
|
||||||
|
@exception Throws DBFException if the passed in file does exist but not a valid DBF file, or if an IO error occurs.
|
||||||
|
*/
|
||||||
|
public DBFWriter( File dbfFile)
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
this.raf = new RandomAccessFile( dbfFile, "rw");
|
||||||
|
|
||||||
|
/* before proceeding check whether the passed in File object
|
||||||
|
is an empty/non-existent file or not.
|
||||||
|
*/
|
||||||
|
if( !dbfFile.exists() || dbfFile.length() == 0) {
|
||||||
|
|
||||||
|
this.header = new DBFHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
header = new DBFHeader();
|
||||||
|
this.header.read( raf);
|
||||||
|
|
||||||
|
/* position file pointer at the end of the raf */
|
||||||
|
this.raf.seek( this.raf.length()-1 /* to ignore the END_OF_DATA byte at EoF */);
|
||||||
|
}
|
||||||
|
catch( FileNotFoundException e) {
|
||||||
|
|
||||||
|
throw new DBFException( "Specified file is not found. " + e.getMessage());
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( e.getMessage() + " while reading header");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.recordCount = this.header.numberOfRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets fields.
|
||||||
|
*/
|
||||||
|
public void setFields( DBFField[] fields)
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
if( this.header.fieldArray != null) {
|
||||||
|
|
||||||
|
throw new DBFException( "Fields has already been set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fields == null || fields.length == 0) {
|
||||||
|
|
||||||
|
throw new DBFException( "Should have at least one field");
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i=0; i<fields.length; i++) {
|
||||||
|
|
||||||
|
if( fields[i] == null) {
|
||||||
|
|
||||||
|
throw new DBFException( "Field " + (i+1) + " is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.header.fieldArray = fields;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if( this.raf != null && this.raf.length() == 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is a new/non-existent file. So write header before proceeding
|
||||||
|
*/
|
||||||
|
this.header.write( this.raf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( "Error accesing file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add a record.
|
||||||
|
*/
|
||||||
|
public void addRecord( Object[] values)
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
if( this.header.fieldArray == null) {
|
||||||
|
|
||||||
|
throw new DBFException( "Fields should be set before adding records");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( values == null) {
|
||||||
|
|
||||||
|
throw new DBFException( "Null cannot be added as row");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( values.length != this.header.fieldArray.length) {
|
||||||
|
|
||||||
|
throw new DBFException( "Invalid record. Invalid number of fields in row");
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i=0; i<this.header.fieldArray.length; i++) {
|
||||||
|
|
||||||
|
if( values[i] == null) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( this.header.fieldArray[i].getDataType()) {
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
if( !(values[i] instanceof String)) {
|
||||||
|
throw new DBFException( "Invalid value for field " + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
if( !( values[i] instanceof Boolean)) {
|
||||||
|
throw new DBFException( "Invalid value for field " + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
if( !( values[i] instanceof Double)) {
|
||||||
|
throw new DBFException( "Invalid value for field " + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
if( !( values[i] instanceof Date)) {
|
||||||
|
throw new DBFException( "Invalid value for field " + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
if( !(values[i] instanceof Double)) {
|
||||||
|
|
||||||
|
throw new DBFException( "Invalid value for field " + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.raf == null) {
|
||||||
|
|
||||||
|
v_records.addElement( values);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
writeRecord( this.raf, values);
|
||||||
|
this.recordCount++;
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( "Error occured while writing record. " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes the set data to the OutputStream.
|
||||||
|
*/
|
||||||
|
public void write( OutputStream out)
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if( this.raf == null) {
|
||||||
|
|
||||||
|
DataOutputStream outStream = new DataOutputStream( out);
|
||||||
|
|
||||||
|
this.header.numberOfRecords = v_records.size();
|
||||||
|
this.header.write( outStream);
|
||||||
|
|
||||||
|
/* Now write all the records */
|
||||||
|
int t_recCount = v_records.size();
|
||||||
|
for( int i=0; i<t_recCount; i++) { /* iterate through records */
|
||||||
|
|
||||||
|
Object[] t_values = (Object[])v_records.elementAt( i);
|
||||||
|
|
||||||
|
writeRecord( outStream, t_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
outStream.write( END_OF_DATA);
|
||||||
|
outStream.flush();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/* everything is written already. just update the header for record count and the END_OF_DATA mark */
|
||||||
|
this.header.numberOfRecords = this.recordCount;
|
||||||
|
this.raf.seek( 0);
|
||||||
|
this.header.write( this.raf);
|
||||||
|
this.raf.seek( raf.length());
|
||||||
|
this.raf.writeByte( END_OF_DATA);
|
||||||
|
this.raf.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch( IOException e) {
|
||||||
|
|
||||||
|
throw new DBFException( e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write()
|
||||||
|
throws DBFException {
|
||||||
|
|
||||||
|
this.write( null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeRecord( DataOutput dataOutput, Object []objectArray)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
dataOutput.write( (byte)' ');
|
||||||
|
for( int j=0; j<this.header.fieldArray.length; j++) { /* iterate throught fields */
|
||||||
|
|
||||||
|
switch( this.header.fieldArray[j].getDataType()) {
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
if( objectArray[j] != null) {
|
||||||
|
|
||||||
|
String str_value = objectArray[j].toString();
|
||||||
|
dataOutput.write( Utils.textPadding( str_value, characterSetName, this.header.fieldArray[j].getFieldLength()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write( Utils.textPadding( "", this.characterSetName, this.header.fieldArray[j].getFieldLength()));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
if( objectArray[j] != null) {
|
||||||
|
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar();
|
||||||
|
calendar.setTime( (Date)objectArray[j]);
|
||||||
|
StringBuffer t_sb = new StringBuffer();
|
||||||
|
dataOutput.write( String.valueOf( calendar.get( Calendar.YEAR)).getBytes());
|
||||||
|
dataOutput.write( Utils.textPadding( String.valueOf( calendar.get( Calendar.MONTH)+1), this.characterSetName, 2, Utils.ALIGN_RIGHT, (byte)'0'));
|
||||||
|
dataOutput.write( Utils.textPadding( String.valueOf( calendar.get( Calendar.DAY_OF_MONTH)), this.characterSetName, 2, Utils.ALIGN_RIGHT, (byte)'0'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write( " ".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
|
||||||
|
if( objectArray[j] != null) {
|
||||||
|
|
||||||
|
dataOutput.write( Utils.doubleFormating( (Double)objectArray[j], this.characterSetName, this.header.fieldArray[j].getFieldLength(), this.header.fieldArray[j].getDecimalCount()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write( Utils.textPadding( "?", this.characterSetName, this.header.fieldArray[j].getFieldLength(), Utils.ALIGN_RIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
|
||||||
|
if( objectArray[j] != null) {
|
||||||
|
|
||||||
|
dataOutput.write(
|
||||||
|
Utils.doubleFormating( (Double)objectArray[j], this.characterSetName, this.header.fieldArray[j].getFieldLength(), this.header.fieldArray[j].getDecimalCount()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write(
|
||||||
|
Utils.textPadding( "?", this.characterSetName, this.header.fieldArray[j].getFieldLength(), Utils.ALIGN_RIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
|
||||||
|
if( objectArray[j] != null) {
|
||||||
|
|
||||||
|
if( (Boolean)objectArray[j] == Boolean.TRUE) {
|
||||||
|
|
||||||
|
dataOutput.write( (byte)'T');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write((byte)'F');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
dataOutput.write( (byte)'?');
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M':
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new DBFException( "Unknown field type " + this.header.fieldArray[j].getDataType());
|
||||||
|
}
|
||||||
|
} /* iterating through the fields */
|
||||||
|
}
|
||||||
|
}
|
||||||
172
dotnetdbf/original java src/Utils.java
Normal file
172
dotnetdbf/original java src/Utils.java
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
Utils
|
||||||
|
Class for contining utility functions.
|
||||||
|
|
||||||
|
This file is part of JavaDBF packege.
|
||||||
|
|
||||||
|
author: anil@linuxense.com
|
||||||
|
license: LGPL (http://www.gnu.org/copyleft/lesser.html)
|
||||||
|
|
||||||
|
$Id: Utils.java,v 1.7 2004/03/31 16:00:34 anil Exp $
|
||||||
|
*/
|
||||||
|
package com.linuxense.javadbf;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.text.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Miscelaneous functions required by the JavaDBF package.
|
||||||
|
*/
|
||||||
|
public final class Utils {
|
||||||
|
|
||||||
|
public static final int ALIGN_LEFT = 10;
|
||||||
|
public static final int ALIGN_RIGHT = 12;
|
||||||
|
|
||||||
|
private Utils(){}
|
||||||
|
|
||||||
|
public static int readLittleEndianInt( DataInput in)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
int bigEndian = 0;
|
||||||
|
for( int shiftBy=0; shiftBy<32; shiftBy+=8) {
|
||||||
|
|
||||||
|
bigEndian |= (in.readUnsignedByte()&0xff) << shiftBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bigEndian;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short readLittleEndianShort( DataInput in)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
int low = in.readUnsignedByte() & 0xff;
|
||||||
|
int high = in.readUnsignedByte();
|
||||||
|
|
||||||
|
return (short )(high << 8 | low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] trimLeftSpaces( byte [] arr) {
|
||||||
|
|
||||||
|
StringBuffer t_sb = new StringBuffer( arr.length);
|
||||||
|
|
||||||
|
for( int i=0; i<arr.length; i++) {
|
||||||
|
|
||||||
|
if( arr[i] != ' ') {
|
||||||
|
|
||||||
|
t_sb.append( (char)arr[ i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t_sb.toString().getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short littleEndian( short value) {
|
||||||
|
|
||||||
|
short num1 = value;
|
||||||
|
short mask = (short)0xff;
|
||||||
|
|
||||||
|
short num2 = (short)(num1&mask);
|
||||||
|
num2<<=8;
|
||||||
|
mask<<=8;
|
||||||
|
|
||||||
|
num2 |= (num1&mask)>>8;
|
||||||
|
|
||||||
|
return num2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int littleEndian(int value) {
|
||||||
|
|
||||||
|
int num1 = value;
|
||||||
|
int mask = 0xff;
|
||||||
|
int num2 = 0x00;
|
||||||
|
|
||||||
|
num2 |= num1 & mask;
|
||||||
|
|
||||||
|
for( int i=1; i<4; i++) {
|
||||||
|
|
||||||
|
num2<<=8;
|
||||||
|
mask <<= 8;
|
||||||
|
num2 |= (num1 & mask)>>(8*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return num2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding( String text, String characterSetName, int length) throws java.io.UnsupportedEncodingException {
|
||||||
|
|
||||||
|
return textPadding( text, characterSetName, length, Utils.ALIGN_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding( String text, String characterSetName, int length, int alignment) throws java.io.UnsupportedEncodingException {
|
||||||
|
|
||||||
|
return textPadding( text, characterSetName, length, alignment, (byte)' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] textPadding( String text, String characterSetName, int length, int alignment,
|
||||||
|
byte paddingByte) throws java.io.UnsupportedEncodingException {
|
||||||
|
|
||||||
|
if( text.length() >= length) {
|
||||||
|
|
||||||
|
return text.substring( 0, length).getBytes( characterSetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte byte_array[] = new byte[ length];
|
||||||
|
Arrays.fill( byte_array, paddingByte);
|
||||||
|
|
||||||
|
switch( alignment) {
|
||||||
|
|
||||||
|
case ALIGN_LEFT:
|
||||||
|
System.arraycopy( text.getBytes( characterSetName), 0, byte_array, 0, text.length());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ALIGN_RIGHT:
|
||||||
|
int t_offset = length - text.length();
|
||||||
|
System.arraycopy( text.getBytes( characterSetName), 0, byte_array, t_offset, text.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return byte_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] doubleFormating( Double doubleNum, String characterSetName, int fieldLength, int sizeDecimalPart) throws java.io.UnsupportedEncodingException{
|
||||||
|
|
||||||
|
int sizeWholePart = fieldLength - (sizeDecimalPart>0?( sizeDecimalPart + 1):0);
|
||||||
|
|
||||||
|
StringBuffer format = new StringBuffer( fieldLength);
|
||||||
|
|
||||||
|
for( int i=0; i<sizeWholePart; i++) {
|
||||||
|
|
||||||
|
format.append( "#");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sizeDecimalPart > 0) {
|
||||||
|
|
||||||
|
format.append( ".");
|
||||||
|
|
||||||
|
for( int i=0; i<sizeDecimalPart; i++) {
|
||||||
|
|
||||||
|
format.append( "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DecimalFormat df = new DecimalFormat( format.toString());
|
||||||
|
|
||||||
|
return textPadding( df.format( doubleNum.doubleValue()).toString(), characterSetName, fieldLength, ALIGN_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains( byte[] arr, byte value) {
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for( int i=0; i<arr.length; i++) {
|
||||||
|
|
||||||
|
if( arr[i] == value) {
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
dotnetdbf/sn.snk
Normal file
BIN
dotnetdbf/sn.snk
Normal file
Binary file not shown.
Reference in New Issue
Block a user