‎2011 Nov 06 10:06 PM
Hi ABAPERs.
Due to I need to read the content of a file which record lenght depends on a value contained in a table, I've implemented the following code (let's say lenght for this record is 72):
DATA: l_o_table_line TYPE REF TO data,
l_o_table TYPE REF TO data,
l_long_reg TYPE i,
l_index_table TYPE i.
FIELD-SYMBOLS: <fs_table_line> TYPE ANY,
<fs_table> TYPE STANDARD TABLE.
CLEAR: l_o_table_line,
l_o_table,
l_long_reg.
l_long_reg = 82.
CREATE DATA l_o_table_line TYPE c LENGTH l_long_reg.
ASSIGN l_o_table_line->* TO <fs_linea_tabla>.
CREATE DATA l_o_table LIKE STANDARD TABLE OF l_o_table_line.
ASSIGN l_o_table->* TO <fs_table>.
* Read the content from the APP Server File
REFRESH <fs_table>.
TRY.
OPEN DATASET d_filename FOR INPUT
IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS.
CATCH cx_root INTO l_o_cx.
l_mens_error = l_o_cx->get_text( ).
ENDTRY.
IF l_mens_error IS INITIAL.
DO.
CLEAR <fs_table_line>.
READ DATASET d_filename INTO <fs_table_line>.
IF sy-subrc IS INITIAL.
APPEND <fs_table_line> TO <fs_table>.
ELSE.
EXIT.
ENDIF.
ENDDO.
CLOSE DATASET d_filename.
ENDIF.
When I execute this code, a dump is being generated in line "APPEND <fs_table_line> TO <fs_table> with this info:
OBJECTS_MOVE_NOT_SUPPORTED
Conversion of type "C" to "l" is not Supported.
Any keys to solve this problem? Does anyone find a problem in either data definion or creation?
Kind Regards.
‎2011 Nov 06 10:17 PM
Hi again.
I've found a similar forum post, but the difference in my problem is that in the older post, the table line type is known when the table is created, and here, I need to know the type of record before creating the table.
Kind Regards.
‎2011 Nov 06 11:15 PM
Solved problem.
I've created the table with the following code:
CREATE DATA l_o_table_line TYPE c LENGHT l_long_ref.
ASSIGN l_o_table_line->* to <fs_table_line>.
CREATE DATA l_o_table LIKE STANDARD TABLE OF <fs_table_line>
WITH KEY table_line.
ASSIGN l_o_table->* to <fs_table>.
Now, when I perform an INSERT <fs_table_line> INTO <fs_table> INDEX ... no dump is triggered.
Kind Regards and hope this could help anyone.
‎2011 Nov 06 11:25 PM
Hello Santiago,
A few comments about your code:
This is not required
CLEAR: l_o_table_line,
l_o_table,
l_long_reg. This is not required
REFRESH <fs_table>.This is incorrect way to handle exception for open dataset
TRY.
OPEN DATASET d_filename FOR INPUT
IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS.
CATCH cx_root INTO l_o_cx.
l_mens_error = l_o_cx->get_text( ).
ENDTRY.
The correct way to handle exception should be
* App server processing
OPEN DATASET iv_filename FOR INPUT IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS
WITH SMART LINEFEED MESSAGE lv_error.
IF sy-subrc NE 0.
MESSAGE e000 WITH text-e02 iv_filename text-e03 lv_error INTO lv_dummy.
RAISE read_error.
ENDIF.
Finally I'm not sure about the last part of your logic but I think your intention is to read a dataset and build an internal table from it dynamically i.e. the structure of the data is only know at run-time. I had developed a similar static method which works fine in our productive system for some time now - below is the code
Definition
CLASS-METHODS format_rawdata
IMPORTING
value(it_rawdata) TYPE string_table
!iv_delimiter TYPE abap_char1 DEFAULT ','
CHANGING
!ct_formatted_data TYPE STANDARD TABLE .
Implementation
METHOD format_rawdata.
*************************************************************
* Author: Sougata Chatterjee
* Date: 16/05/2011
* Purpose: Format Raw Data into ANY internal table structure
* Reason: Development of Reusable Cross Application Objects
*************************************************************
FIELD-SYMBOLS:
<ls_rawdata> TYPE string,
<ls_string> TYPE string,
<ls_data> TYPE ANY,
<l_struc_field> TYPE ANY.
DATA:
lt_stringtab TYPE string_table,
ls_data TYPE REF TO data.
CREATE DATA ls_data LIKE LINE OF ct_formatted_data.
ASSIGN ls_data->* TO <ls_data>.
LOOP AT it_rawdata ASSIGNING <ls_rawdata>.
CLEAR:
lt_stringtab,
<ls_data>.
SPLIT <ls_rawdata> AT iv_delimiter INTO TABLE lt_stringtab.
DO.
READ TABLE lt_stringtab ASSIGNING <ls_string> INDEX sy-index.
IF sy-subrc <> 0.
EXIT.
ELSE.
ASSIGN COMPONENT sy-tabix OF STRUCTURE <ls_data> TO <l_struc_field>.
<l_struc_field> = <ls_string>.
ENDIF.
ENDDO.
APPEND <ls_data> TO ct_formatted_data.
ENDLOOP.
ENDMETHOD.
Hope this helps.
Cheers,
Sougata.
‎2011 Nov 07 4:59 AM
This is incorrect way to handle exception for open dataset
TRY.
OPEN DATASET d_filename FOR INPUT
IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS.
CATCH cx_root INTO l_o_cx.
l_mens_error = l_o_cx->get_text( ).
ENDTRY.The correct way to handle exception should be
* App server processing
OPEN DATASET iv_filename FOR INPUT IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS
WITH SMART LINEFEED MESSAGE lv_error.
IF sy-subrc NE 0.
MESSAGE e000 WITH text-e02 iv_filename text-e03 lv_error INTO lv_dummy.
RAISE read_error.
ENDIF.Hello Sougata,
The way OP is handling the exceptions is correct. Why do you say otherwise, any specifics?
BR,
Suhas
‎2011 Nov 07 5:33 AM
Hello Suhas,
1. You can try putting the cursor on OPEN DATASET statement then hit F1. After that please click on the link error_handling which will then list the best practices for exception handling on OPEN DATASET command.
2. If you still are in disbelief, you can debug through the small program I've written below for you and find out for yourself that the TRY-CATCH block is practically useless for e.g. when the file could not be found to be opened for read/write.
REPORT zsctest NO STANDARD PAGE HEADING.
DATA:
lo_cx TYPE REF TO cx_root,
lv_error TYPE string,
lv_file TYPE localfile VALUE '/FOLDER/I DO NOT EXIST.txt'.
START-OF-SELECTION.
BREAK-POINT.
TRY.
OPEN DATASET lv_file FOR INPUT
IN TEXT MODE
ENCODING DEFAULT IGNORING CONVERSION ERRORS.
CATCH cx_root INTO lo_cx.
lv_error = lo_cx->get_text( ).
ENDTRY.
END-OF-SELECTION.
WRITE: 'Sy-Subrc = ', sy-subrc.
I hope this reinstates the fact the Santiago's exception handling is incorrect for OPEN DATASET as I had stated earlier.
Cheers,
Sougata.
‎2011 Nov 07 6:08 AM
Thanks for the info.
I'll check carefully your code to determine whether I can use any.
Kind Regards.
‎2011 Nov 07 6:50 AM
Hello Sougata,
You can try putting the cursor on OPEN DATASET statement then hit F1. After that please click on the link error_handling which will then list the best practices for exception handling on OPEN DATASET command.
The error_handling you've mentioned is not synonymous with exception handling. OPEN DATASET raises the following treatable exceptions: CX_SY_FILE_OPEN, CX_SY_CODEPAGE_CONVERTER_INIT, CX_SY_CONVERSION_CODEPAGE, CX_SY_FILE_AUTHORITY, CX_SY_PIPES_NOT_SUPPORTED & CX_SY_TOO_MANY_FILES.
So when i say exception handling, i mean handling these exceptions which cannot be treated via the error handling options(except CX_SY_CONVERSION_CODEPAGE ).
If you still are in disbelief, you can debug through the small program I've written below for you and find out for yourself that the TRY-CATCH block is practically useless for e.g. when the file could not be found to be opened for read/write.
The SY-SUBRC value only tells whether you're able to open the file or not. More specific info, as to why the file could not be opened, can be obtained from the exception objects.
For e.g., if you don't have authority to read a certain file, how are you supposed to handle that exception? Of course you can check the auth. obj. S_DATASET or use the FM AUTHORITY_CHECK_DATASET to check the authority, but imo it can be done more elegantly by handling the exception CX_SY_FILE_AUTHORITY.
Please enlighten me, if you think otherwise!
BR,
Suhas
PS: The use of generic exception object CX_ROOT should be discouraged though. The exception handling should be as much specific as possible.
‎2011 Nov 07 8:41 AM
Hello Suhas,
My comments below:
The error_handling you've mentioned is not synonymous with exception handling.
Yes it is - I'll come to that in a moment.
OPEN DATASET raises the following treatable exceptions: CX_SY_FILE_OPEN, CX_SY_CODEPAGE_CONVERTER_INIT, CX_SY_CONVERSION_CODEPAGE, CX_SY_FILE_AUTHORITY, CX_SY_PIPES_NOT_SUPPORTED & CX_SY_TOO_MANY_FILES.
Agreed but not the point here...
So when i say exception handling, i mean handling these exceptions which cannot be treated via the error handling options(except CX_SY_CONVERSION_CODEPAGE ).
You are wrong - all of the above exceptions can be treated via the error handling option in the following way:
DATA: lv_message TYPE string.
OPEN DATASET pa_file FOR INPUT IN TEXT MODE
ENCODING DEFAULT WITH SMART LINEFEED
MESSAGE lv_message. "<----- using the MESSAGE addition
IF sy-subrc NE 0.
" exception handling goes here...
MESSAGE e099 WITH 'File' pv_file 'could not be opened because' lv_message.
ENDIF.
The SY-SUBRC value only tells whether you're able to open the file or not. More specific info, as to why the file could not be opened, can be obtained from the exception objects.
You are wrong again - refer above code and explanantion -> variable lv_message now contains the reason why the file could not be opened.
For e.g., if you don't have authority to read a certain file, how are you supposed to handle that exception? Of course you can check the auth. obj. S_DATASET or use the FM AUTHORITY_CHECK_DATASET to check the authority, but imo it can be done more elegantly by handling the exception CX_SY_FILE_AUTHORITY.
Do not agree - there are catchable exceptions and also some non-catchable exceptions for OPEN DATASET - in that case why would a good developer bother to CATCH (and how many!) when the MESSAGE addition returns the operating system messages and is full proof ?? The example program in my previous post clearly shows that no class based exceptions are raised when an error occured at OPEN DATASET.
As I already stated in my last post, the TRY-CATCH block is useless for exception/error handling in regards to the OPEN DATASET command for example when file does not exist in the App Server etc.
Here's a little challenge for you:
Considering a user has authority to read a dataset - try opening a dataset which does not exist in the App Server by handling all exceptions via the TRY-CATCH block. The program should not use the MESSAGE addition at all. The exception (that the file does not exist) should be caught by the exception class used within the TRY-CATCH block. Print the error message and show us!
Good luck!
Sougata.
‎2011 Nov 07 11:38 AM
Here's a little challenge for you:
Considering a user has authority to read a dataset - try opening a dataset which does not exist in the App Server by handling all exceptions via the TRY-CATCH block. The program should not use the MESSAGE addition at all. The exception (that the file does not exist) should be caught by the exception class used within the TRY-CATCH block. Print the error message and show us!
You can't because SAP runtime doesn't raise an EXCEPTION for this, it just sets SY-SUBRC to a non-zero value. The MESSAGE addition returns the App Server OS messages which are raised if there is some problem while opening the file.
The MESSAGE addition & the TRY-CATCH block are completely disjoint. Using MESSAGE option you don't handle any EXCEPTIONS, rather it is a medium using which OS layer messages are captured. If you don't use this addition, your program doesn't dump.
On the other hand the TRY-CATCH block helps you handle the SAP exceptions which might be raised for the OPEN DATASET, and if you don't use it you might end up getting a runtime error!
... there are catchable exceptions and also some non-catchable exceptions for OPEN DATASET, in that case why would a good developer bother to CATCH (and how many!)
I'm sure most of us would agree a good developer should handle as many exceptions as possible. And the exception handling should be as much specific as possible.
BR,
Suhas