Archive for December, 2006

my first c# test, extracting and renaming first entrty in zip files

Tuesday, December 19th, 2006

I’ve never done any c# coding before, but honest to say, I do have been a (tiny) bit curious on it. It looks a lot like my old favourite java, and it almost smells like java.

My case now was that I needed to extract the first instance in ~1500 zip files from a folder in windows and rename each extracted file to the same name as the zip file (not the extension name of cource). Furthermore the zipfiles where named with “two file extensions” meaning they could be called blabla.eps.zip (or even worse – blabla.jpg.zip which is really odd).

Anyway. As a none Microsoftish or .netish guy in most aspects I found a great IDE/RAD for c# that is GPL:d – SharpDevelop. The install file is around 4.5mb (compared to MS Visual studio for C# cd image beign ~440mb). They also ship a native GPL:d zip library (http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx) for C# that’s really easy to use.

Screen capture of Sharpdevelop

My small but efficient result examplifies how to read a directory, file info, zip contents and how to extract zipfiles:

  1.  
  2.       textBoxResults.Text = "Starting to process zip files in dir " + textBoxDir.Text + Environment.NewLine;
  3.       DirectoryInfo ourDir = new DirectoryInfo(textBoxDir.Text);
  4.       FileInfo[] ourZipFiles = ourDir.GetFiles("*.zip");
  5.       int noFiles = ourZipFiles.Length;
  6.       textBoxResults.Text += "Found " + noFiles + " zip files to extract:" + Environment.NewLine;
  7.       for (int y=0;y<ourZipFiles.Length;y++) {
  8.         textBoxResults.Text += "Extracting " + ourZipFiles[y].FullName + ".. ";
  9.         //extract contents
  10.         //give us a zip rep
  11.         try {
  12.           ZipFile zf = new ZipFile(ourZipFiles[y].FullName);
  13.           //get first entry and extract it..
  14.           foreach (ZipEntry ze in zf) {
  15.             if (ze.CanDecompress && ze.IsFile) {
  16.               //ok. we can extract something. lets do it then. set up fastzip to do it..
  17.               FastZip fz = new FastZip();
  18.               fz.ExtractZip(zf.Name, textBoxOutDir.Text,ze.Name);
  19.               FileInfo tmpfi = new FileInfo(textBoxOutDir.Text + ze.Name);
  20.               //change file extension
  21.               string full = tmpfi.FullName;
  22.               //textBoxResults.Text += "FULL: " + full + Environment.NewLine + " short: " +  + Environment.NewLine;
  23.               string newFileName = tmpfi.Directory.FullName + "" + ourZipFiles[y].Name.Substring(0,ourZipFiles[y].Name.Length-7) + tmpfi.Name.Substring(tmpfi.Name.Length-3);
  24.               //rename
  25.               try {
  26.               //  textBoxResults.Text += "from filename " + tmpfi.FullName + " to " +newFileName;
  27.                 tmpfi.MoveTo(newFileName);
  28.               } catch (IOException ioex) {
  29.                 throw new ZipException("can’t move file; extracted file not found " + ioex.Message);
  30.               }
  31.               textBoxResults.Text +=  ze.Name + " (renamed to " + newFileName + ") ";
  32.               break; //break iteration after first valid zip entry. for now we only want the first one..
  33.             }
  34.           }
  35.           textBoxResults.Text += "..done :) "+ Environment.NewLine;
  36.         } catch(ZipException zex) {
  37.           textBoxResults.Text += "..failed :( ERROR CAUSE: " + zex.Message + Environment.NewLine;
  38.         }
  39.        
  40.       }
  41.  

To summarize I use the following components (not noting gui stuff):
* DirectoryInfo – read/modify directory data
* FileInfo – read/modify file data (not content)
* ZipFile – a zip file representation and functions.
* ZipEntry – a file or folder in a ZipFile.
* FastZip – easy to use utility to ie extract files from zip.

Also note the use of Environment.NewLine to create correct newline/carriage return (std \n\r) in a string. … I tried to use escape style but that seems not to be valid..

Go ahead and download full source code including my sharpdevelop project file attached to this post as zip archive. MultiZipExtractor source codes

Note that to use the ziplibrary you need to add the compiled version as a reference. In sharpdevelop that’s done by selecting the project tab to the left, and right click on references in your project. Browse the dll file and add it. Then just add an extra use line in you code.

Handling localization of database relation fields in a good way..

Monday, December 18th, 2006

With Typo3.
When you use database relation fields in an extension you get problems with localizations as all localized/unlocalized records are selectable for each localization version of your record.

As I couldn’t find anything about this easily when googling (or posting in t3 english newsgroup) I thought it would be valuable to write a few lines about it here.

The first thing I did was, after a tip from someone who I can’t remember gave me the tip to alter the foreign table where clause like this


"foreign_table_where" => "AND sys_language_uid in (-1,0)

in the tca definition (tca.php) of the extension.

This restricts my selection to only do relations against either “all” or “default” language for any translation. However it still leads to data inconsistancy as I don’t want this to be different to each language, but reflected from default language settings. Then I found the l10n_mode for the TCA.

Doing the following hides my field for localized records though still selectable in the default language.


"l10n_mode" => "exclude",

Se the TCA reference[1] table for details.

[1] http://typo3.org/documentation/document-library/core-documentation/doc_core_api/4.0.0/view/4/1/

Altering behavior of existing extensions in Typo3 through the TCA

Monday, December 18th, 2006

I’ve learnt some really nice things the last days with Typo3. I got familiar with the TCA. The TCA [1] controls behavior and data for tables in Typo3. I needed to change the Country field in tt_address from being a boring string input field to become a dropdown selection field. I’m amazed over how simple this is to accomplish.

I got a custom extension mostly generated using the extension kickstarter [2]. That extension adds a lot of extra tables and record types for my client. Amongs these a list of countries and regions for each countries. I wanted to connect these countries to a tt_address record and by that replace the standard country string input field.

This is done easily by editing my ext_tables.php and add the following piece of code:

  1.  
  2. //
  3. // modify tt_address country field to be a dropdown..
  4. //
  5. $ttAddressModCols = Array (
  6.     "country" => Array (   
  7.       "exclude" => 1,  
  8.       "label" => "LLL:EXT:lang/locallang_general.xml:LGL.country"//we’ll borrow the original title for country fields 
  9.     "config" => Array (
  10.       "type" => "select"
  11.       "items" => Array (
  12.         Array("",0),
  13.       ),
  14.       "foreign_table" => "tx_mereaclientname_countries"
  15.       "foreign_table_where" => "ORDER BY tx_mereaclientname_countries.uid"
  16.       "size" => 1
  17.       "minitems" => 0,
  18.       "maxitems" => 1,
  19.     )
  20.   ),
  21. );
  22.  
  23. t3lib_div::loadTCA("tt_address");
  24. t3lib_extMgm::addTCAcolumns("tt_address",$ttAddressModCols,1);
  25.  

That’s it :)

What it does is; create a temporary array of settings for the tt_address table called ttAddressModCols and define a new definition of the country field for tt_address (replacing the current) with my database relation field. It uses the standard country label translation for consistancy. Finaly load tt_address’ TCA definition and merge it with our adaptation.

[update 2006-12-18]
Noteworthy when doing like above is that data is stored in the original database field. You might want to replace that field as well with your own type. For the above I would go with


alter table tt_address change country country INTEGER

in the sql script of my extension. Feels a bit wrong to use varchar to store integers… ;-)

REFERENCES:
[1]http://typo3.org/documentation/document-library/core-documentation/doc_core_api/4.0.0/view/4/1/
[2] http://typo3.org/extensions/repository/view/kickstarter/0.3.8/